提供者和消费者问题
Provider and consumer issue
我对 flutter 还很陌生,我正在尝试使用 provider 包提高我的状态管理技能。我在加载我的类别和通知听众何时显示我的类别小部件而不是我的 modalprogressHUD
时遇到了一些困难
这里是 MyApp class:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<LoginProvider>(
create: (_) => LoginProvider(),
),
ChangeNotifierProvider<CatergoryProvider>(
create: (_) => CatergoryProvider(),
),
ChangeNotifierProvider<RegistrationProvider>(
create: (_) => RegistrationProvider(),
),
ChangeNotifierProvider<QuestionProvider>(
create: (_) => QuestionProvider(),
),
],
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData.dark().copyWith(
primaryColor: Colors.teal,
),
initialRoute: DashBoard.id,
routes: {
WelcomeScreen.id: (context) => WelcomeScreen(),
DashBoard.id: (context) => DashBoard(),
QuizzPage.id: (context) => QuizzPage()
},
),
);
}
}
我的分类供应商class:
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:quizz_app/models/catergory.dart';
import 'package:quizz_app/services/services.dart';
class CatergoryProvider with ChangeNotifier {
List<Catergory> catergory;
String errorMessage;
bool loading = false;
Future<bool> fetchCatergory() async {
setLoading(true);
await Service(url: "https://quizapp1234.herokuapp.com/kategori")
.fetchCatergory()
.then((data) {
if (data.statusCode == 200) {
print('success');
Iterable l = json.decode(data.body);
setCatergory(
List<Catergory>.from(l.map((data) => Catergory.fromJson(data))));
setLoading(false);
} else {
Map<String, dynamic> result = json.decode(data.body);
setMessage(result['message']);
}
});
return isList();
}
bool isLoading() {
return loading;
}
void setLoading(value) {
loading = value;
notifyListeners();
}
void setCatergory(value) {
catergory = value;
notifyListeners();
}
void setMessage(value) {
errorMessage = value;
notifyListeners();
}
List<Catergory> getList() {
return catergory;
}
String getMessage() {
return errorMessage;
}
bool isList() {
return catergory != null ? true : false;
}
}
这里是我包装我想要通知消费者的内容:
Consumer<CatergoryProvider>(
builder: (context, catergory, child) {
catergory.fetchCatergory();
catergories = catergory.getList();
return catergory.isLoading()
? ModalProgressHUD(
opacity: 0,
inAsyncCall:
Provider.of<CatergoryProvider>(context).isLoading(),
child: Scaffold())
: catergoryPage(catergories, context);
},
),
我的调试控制台:
════════ Exception caught by foundation library ════════════════════════════════
setState() or markNeedsBuild() called during build.
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by foundation library ════════════════════════════════
setState() or markNeedsBuild() called during build.
════════════════════════════════════════════════════════════════════════════════
发生的异常:
Exception has occurred.
FlutterError (A CatergoryProvider was used after being disposed.
Once you have called dispose() on a CatergoryProvider, it can no longer be used.)
在 builder:
内的 Consumer 中调用 fetchCatergory
,在 fetchCatergory
方法中调用调用 notifyListeners()
的函数,每次调用 notifyListeners()
时, builder:
被召回,导致无限循环
仅当 getList()
returns 为 null 且 isLoading()
为 false
时才尝试换行 catergory.fetchCatergory()
代码:
Consumer<CatergoryProvider>(
builder: (context, catergory, child) {
if(!catergory.isLoading() && catergory.getList() == null) {
catergory.fetchCatergory();
}
catergories = catergory.getList();
return catergory.isLoading()
? ModalProgressHUD(
opacity: 0,
inAsyncCall:
Provider.of<CatergoryProvider>(context).isLoading(),
child: Scaffold())
:
catergoryPage(catergories, context);
},
),
我对 flutter 还很陌生,我正在尝试使用 provider 包提高我的状态管理技能。我在加载我的类别和通知听众何时显示我的类别小部件而不是我的 modalprogressHUD
时遇到了一些困难这里是 MyApp class:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<LoginProvider>(
create: (_) => LoginProvider(),
),
ChangeNotifierProvider<CatergoryProvider>(
create: (_) => CatergoryProvider(),
),
ChangeNotifierProvider<RegistrationProvider>(
create: (_) => RegistrationProvider(),
),
ChangeNotifierProvider<QuestionProvider>(
create: (_) => QuestionProvider(),
),
],
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData.dark().copyWith(
primaryColor: Colors.teal,
),
initialRoute: DashBoard.id,
routes: {
WelcomeScreen.id: (context) => WelcomeScreen(),
DashBoard.id: (context) => DashBoard(),
QuizzPage.id: (context) => QuizzPage()
},
),
);
}
}
我的分类供应商class:
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:quizz_app/models/catergory.dart';
import 'package:quizz_app/services/services.dart';
class CatergoryProvider with ChangeNotifier {
List<Catergory> catergory;
String errorMessage;
bool loading = false;
Future<bool> fetchCatergory() async {
setLoading(true);
await Service(url: "https://quizapp1234.herokuapp.com/kategori")
.fetchCatergory()
.then((data) {
if (data.statusCode == 200) {
print('success');
Iterable l = json.decode(data.body);
setCatergory(
List<Catergory>.from(l.map((data) => Catergory.fromJson(data))));
setLoading(false);
} else {
Map<String, dynamic> result = json.decode(data.body);
setMessage(result['message']);
}
});
return isList();
}
bool isLoading() {
return loading;
}
void setLoading(value) {
loading = value;
notifyListeners();
}
void setCatergory(value) {
catergory = value;
notifyListeners();
}
void setMessage(value) {
errorMessage = value;
notifyListeners();
}
List<Catergory> getList() {
return catergory;
}
String getMessage() {
return errorMessage;
}
bool isList() {
return catergory != null ? true : false;
}
}
这里是我包装我想要通知消费者的内容:
Consumer<CatergoryProvider>(
builder: (context, catergory, child) {
catergory.fetchCatergory();
catergories = catergory.getList();
return catergory.isLoading()
? ModalProgressHUD(
opacity: 0,
inAsyncCall:
Provider.of<CatergoryProvider>(context).isLoading(),
child: Scaffold())
: catergoryPage(catergories, context);
},
),
我的调试控制台:
════════ Exception caught by foundation library ════════════════════════════════
setState() or markNeedsBuild() called during build.
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by foundation library ════════════════════════════════
setState() or markNeedsBuild() called during build.
════════════════════════════════════════════════════════════════════════════════
发生的异常:
Exception has occurred.
FlutterError (A CatergoryProvider was used after being disposed.
Once you have called dispose() on a CatergoryProvider, it can no longer be used.)
在 builder:
内的 Consumer 中调用 fetchCatergory
,在 fetchCatergory
方法中调用调用 notifyListeners()
的函数,每次调用 notifyListeners()
时, builder:
被召回,导致无限循环
仅当 getList()
returns 为 null 且 isLoading()
为 false
catergory.fetchCatergory()
代码:
Consumer<CatergoryProvider>(
builder: (context, catergory, child) {
if(!catergory.isLoading() && catergory.getList() == null) {
catergory.fetchCatergory();
}
catergories = catergory.getList();
return catergory.isLoading()
? ModalProgressHUD(
opacity: 0,
inAsyncCall:
Provider.of<CatergoryProvider>(context).isLoading(),
child: Scaffold())
:
catergoryPage(catergories, context);
},
),