Flutter 如何将ChangeNotifier与Navigator一起使用
在我的应用程序中,我有一个模型存储登录到我的应用程序的用户Flutter 如何将ChangeNotifier与Navigator一起使用,flutter,dart,Flutter,Dart,在我的应用程序中,我有一个模型存储登录到我的应用程序的用户 class AuthenticationModel extends ChangeNotifier { User _user; User get user => _user; void authenticate(LoginData loginData) async { // _user = // get user from http call notifyListeners(); } void
class AuthenticationModel extends ChangeNotifier {
User _user;
User get user => _user;
void authenticate(LoginData loginData) async {
// _user = // get user from http call
notifyListeners();
}
void restoreUser() async {
//_user = // get user from shared prefs
notifyListeners();
}
}
模型注册在小部件树的顶部:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => AuthenticationModel(),
child: MaterialApp(
title: 'My App',
initialRoute: '/',
routes: {
'/': (context) => PrehomeScreen(),
'/home': (context) => HomeScreen()
},
),
);
}
}
在小部件树的某个地方,我有一个按钮调用模型:
child: Consumer<AuthenticationModel>(
builder: (context, authModel, child) {
return MyCustomButton(
text: 'Connect',
onPressed: () {
authModel.authenticate(...)
},
);
},
),
但这样做时我有一个错误:
════════ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
setState() or markNeedsBuild() called during build.
The relevant error-causing widget was:
Consumer<AuthenticationModel> file:///Users/pierre.degand/Projects/cdc/course_du_coeur/lib/Prehome.dart:13:12
═══════════════════════════════════════════════════════════════════════════════
它工作正常,在模型更改时执行导航。但控制台中有一条错误消息(打印3次):
该应用程序不会崩溃,所以,现在,我同意这一点。
我仍然想知道这是否是一种好方法。我更喜欢使用Stream或rxdart PublishSubject行为主题收听任何活动或管理全球应用程序数据 我使用bloc模式实现它。基本上,bloc模式就像react的redux,这意味着创建一个包含所有应用程序数据的中心数据集,而您不必进行道具钻取 您可以像这样创建流
import 'package:rxdart/rxdart.dart';
class AbcBloc {
BehaviorSubject<bool> _connectivity;
AbcBloc() {
_connectivity = BehaviorSubject<bool>();
}
// stream
Stream<bool> get connectivity => _connectivity.stream;
// sink
Function(bool) get updateConnectivity => _connectivity.sink.add;
dispose(){
_connectivity.close();
}
}
void createAbcBloc() {
if (abcBloc != null) {
abcBloc.dispose();
}
abcBloc = AbcBloc();
}
AbcBloc abcBloc = AbcBloc();
您可以从abcBloc.updateConnectivity(false)更新连接;
每次执行任何更改时,侦听器都将被调用
记住,您必须调用ListenConnection()一次才能激活它 我更喜欢使用Stream或rxdart PublishSubject行为主题收听任何活动或管理全球应用程序数据
void main() {
Provider.debugCheckInvalidValueType = null;
return runApp(
Provider(
create: (_) => AuthenticationModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final navigatorKey = GlobalKey<NavigatorState>();
Provider.of<AuthenticationModel>(context).addListener(() {
final authModel = Provider.of<AuthenticationModel>(context);
if (authModel.user != null) {
navigatorKey.currentState.pushReplacementNamed("/home");
}
});
return MaterialApp(
navigatorKey: navigatorKey,
title: 'My App',
initialRoute: '/',
routes: {
'/': (context) => PrehomeScreen(),
'/home': (context) => HomeScreen()
},
);
}
}
我使用bloc模式实现它。基本上,bloc模式就像react的redux,这意味着创建一个包含所有应用程序数据的中心数据集,而您不必进行道具钻取
您可以像这样创建流
import 'package:rxdart/rxdart.dart';
class AbcBloc {
BehaviorSubject<bool> _connectivity;
AbcBloc() {
_connectivity = BehaviorSubject<bool>();
}
// stream
Stream<bool> get connectivity => _connectivity.stream;
// sink
Function(bool) get updateConnectivity => _connectivity.sink.add;
dispose(){
_connectivity.close();
}
}
void createAbcBloc() {
if (abcBloc != null) {
abcBloc.dispose();
}
abcBloc = AbcBloc();
}
AbcBloc abcBloc = AbcBloc();
您可以从abcBloc.updateConnectivity(false)更新连接;
每次执行任何更改时,侦听器都将被调用
记住,您必须调用ListenConnection()一次才能激活它 void main(){
void main() {
Provider.debugCheckInvalidValueType = null;
return runApp(
Provider(
create: (_) => AuthenticationModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final navigatorKey = GlobalKey<NavigatorState>();
Provider.of<AuthenticationModel>(context).addListener(() {
final authModel = Provider.of<AuthenticationModel>(context);
if (authModel.user != null) {
navigatorKey.currentState.pushReplacementNamed("/home");
}
});
return MaterialApp(
navigatorKey: navigatorKey,
title: 'My App',
initialRoute: '/',
routes: {
'/': (context) => PrehomeScreen(),
'/home': (context) => HomeScreen()
},
);
}
}
Provider.debugCheckInvalidValueType=null;
返回runApp(
提供者(
创建:(\u)=>AuthenticationModel(),
子项:MyApp(),
),
);
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
最终navigatorKey=GlobalKey();
Provider.of(context.addListener)(){
最终authModel=Provider.of(上下文);
if(authModel.user!=null){
navigatorKey.currentState.pushReplacementNamed(“/home”);
}
});
返回材料PP(
导航工作:导航工作,
标题:“我的应用程序”,
initialRoute:“/”,
路线:{
“/”:(上下文)=>PrehomeScreen(),
“/home”:(上下文)=>主屏幕()
},
);
}
}
void main(){
Provider.debugCheckInvalidValueType=null;
返回runApp(
提供者(
创建:(\u)=>AuthenticationModel(),
子项:MyApp(),
),
);
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
最终navigatorKey=GlobalKey();
Provider.of(context.addListener)(){
最终authModel=Provider.of(上下文);
if(authModel.user!=null){
navigatorKey.currentState.pushReplacementNamed(“/home”);
}
});
返回材料PP(
导航工作:导航工作,
标题:“我的应用程序”,
initialRoute:“/”,
路线:{
“/”:(上下文)=>PrehomeScreen(),
“/home”:(上下文)=>主屏幕()
},
);
}
}
我认为不需要变更通知程序
void main() async {
final isLoggedIn = await Future.value(true); // get value from shared prefs or your model
runApp(MyApp(isLoggedIn));
}
class MyApp extends StatelessWidget {
MyApp(this.isLoggedIn);
final bool isLoggedIn;
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: isLoggedIn ? '/home' : '/',
routes: {
'/': (context) => HomeScreen(),
'/login': (context) => LoginScreen()
},
);
}
}
我认为不需要ChangeNotifier
void main() async {
final isLoggedIn = await Future.value(true); // get value from shared prefs or your model
runApp(MyApp(isLoggedIn));
}
class MyApp extends StatelessWidget {
MyApp(this.isLoggedIn);
final bool isLoggedIn;
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: isLoggedIn ? '/home' : '/',
routes: {
'/': (context) => HomeScreen(),
'/login': (context) => LoginScreen()
},
);
}
}
它不起作用。我还试着用消费者
包装材料应用
,但效果不太好。我找到了一种方法,可以让这部作品在我的第一篇文章中看到编辑。我已经编辑过了。我认为,PrehomeScreen
是不必要的小部件。它不工作。我还试着用消费者
包装材料应用
,但效果不太好。我找到了一种方法,可以让这部作品在我的第一篇文章中看到编辑。我已经编辑过了。我认为PrehomeScreen
是不必要的小部件。
void main() async {
final isLoggedIn = await Future.value(true); // get value from shared prefs or your model
runApp(MyApp(isLoggedIn));
}
class MyApp extends StatelessWidget {
MyApp(this.isLoggedIn);
final bool isLoggedIn;
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: isLoggedIn ? '/home' : '/',
routes: {
'/': (context) => HomeScreen(),
'/login': (context) => LoginScreen()
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
child: Text('Logout'),
onPressed: () => Navigator.of(context).pushReplacementNamed("/login"),
);
}
}
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
child: Text('Login'),
onPressed: () => Navigator.of(context).pushReplacementNamed("/"),
);
}
}