我正在使用提供程序包来处理来自不同位置的数据。对于这个问题,我创建了一个示例项目,其中包括一个显示“登录”按钮的欢迎屏幕,单击该按钮后,它会重定向到“登录屏幕”,在该屏幕上将有一个登录文本字段,但现在,我放置了一个按钮,用于单击呼叫登录功能,该登录功能会通知侦听器。我还具有注销功能和布尔值,可以跟踪已登录状态。
这些函数和值位于auth.provider.dart
lib文件夹中的providers目录中的文件中。
import 'package:flutter/foundation.dart';
class Auth with ChangeNotifier {
var _loggedIn = false;
bool get loggedIn => _loggedIn;
void loginUser() {
_loggedIn = true;
print('Logged in');
notifyListeners();
}
void logout() {
_loggedIn = false;
print('Logged out');
notifyListeners();
}
}
我在main.dart中提供了提供程序,并且还在使用Consumer:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Auth>(
create: (_) => Auth(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Consumer<Auth>(
builder: (_, auth, __) {
print('main.dart logged in: ${auth.loggedIn}');
if(auth.loggedIn) return HomeScreen();
return WelcomeScreen();
},
),
routes: {
LoginScreen.routeName: (ctx) => LoginScreen(),
HomeScreen.routeName: (ctx) => HomeScreen(),
},
),
);
}
}
在上面的文件中,我只是检查是否loggedIn
为真。如果未显示,则显示欢迎屏幕,以便用户可以登录,但是如果用户登录,则直接显示主屏幕。还已在消费者的构建器中放置了一条打印语句,以便每当收到有关身份验证数据的任何更改的通知时,它将打印状态。该程序在应用程序启动时运行一次,并且不再运行。
登录屏幕上没有什么东西,只有一个脚手架和一个调用登录功能的登录按钮。
RaisedButton(
child: Text('Click to Login'),
onPressed: () {
Provider.of<Auth>(context, listen: false).loginUser();
},
),
现在单击登录按钮,它将loggedIn
布尔值设置为true并通知侦听器应为Consumer,但main.dart中的Consumer永远不会收到通知。它不会触发更改,有一种条件会检查登录是否为真,然后显示主屏幕,但屏幕完全不会更改。必须手动使用Navigator
以移至主屏幕,并且在主屏幕上有一个注销按钮,该按钮仅设置loggedIn
为false,一旦发生,它应该通知消费者,但又没有通知。
现在,这使我想到一个问题:提供程序中的侦听器如何工作?它何时通知侦听器更改?它是否不会通知更改是否发生了超过上一级别的下降,如上面的示例,Consumer在main.dart中,并且发生了2级别的下降main.dart > WelcomeScreen > LoginScreen
。如何让消费者main.dart
知道其使用的基础数据已更改?
如果您想快速开始使用上面的示例,请参见存储库链接。
我经历了您的github代码。
使用pushReplacementNamed进入登录屏幕
最初-> main.dart-> welcomeScreen->(on-clicking-loginbtn)-> LoginScreen
这里,
1)消费者不在收听(因为您最初的main.dart屏幕已替换为登录页面,并且当前不存在正在收听的页面上)
2)没有导航器可以返回(因为页面不在堆栈中而被替换)
使用pushNamed进入登录屏幕
最初-> main.dart-> welcomeScreen->(on-clicking-loginbtn)-> LoginScreen
这里,
1)消费者正在收听(因为您的主main.dart屏幕没有被替换并且当前存在于页面中。但是您没有看到更改,因为您已在堆栈的上方用登录屏幕覆盖了主初始页面)
2)有导航器可以返回主屏幕(现在您可以使用后退箭头返回以查看更改)
结论如果该页面被其他页面替换,则该页面将无法收听更改的提供者值。它应该在屏幕上聆听。
可以使用的图案
main.dart(home参数)
home: Consumer<Auth>(
builder: (_, auth, __) {
print('main.dart logged in: ${auth.loggedIn}');
if(auth.loggedIn) return HomeScreen();
return WelcomeScreen();
},
)
WelcomeScreen(登录代码)
RaisedButton(
child: Text('Login'),
onPressed: () => Navigator.of(context).pushReplacementNamed(LoginScreen.routeName),
)
LoginScreen(登录按钮)
RaisedButton(
child: Text('Click to Login'),
onPressed: () {
Provider.of<Auth>(context, listen: false).loginUser();
Navigator.of(context).pushReplacementNamed('/');
},
)
主屏幕(退出btn)
RaisedButton(
child: Text('Logout'),
onPressed: () {
Provider.of<Auth>(context, listen: false).logout();
Navigator.of(context).pushReplacementNamed('/');
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句