提供者登录注销颤动
Posted
技术标签:
【中文标题】提供者登录注销颤动【英文标题】:Provider login logout flutter 【发布时间】:2020-12-06 20:27:23 【问题描述】:我正在尝试使用 Provider 创建一个简单的身份验证流程。我有三页:
-
登录页面
入职页面
主页
这个应用的流程是:
-
如果用户第一次打开应用程序,他/她将被重定向到入门,然后登录到主页。
对于第二次用户,应用首先检查登录状态并重定向到登录 -> 主页或直接到主页。
这是我在代码中的设置:
main.dart
void main()
runApp(MultiProvider(providers: [
ChangeNotifierProvider<StorageHelper>(create: (_) => StorageHelper()),
ChangeNotifierProvider<AuthProvider>(create: (_) => AuthProvider()),
], child: MyApp()));
class MyApp extends StatelessWidget
Widget build(BuildContext context)
return Consumer<AuthProvider>(builder: (final BuildContext context,
final AuthProvider authProvider, final Widget child)
print(authProvider.isAuthenticated); // this is false whenever I //click the logout from category(or other pushed pages) but the below ternary //operation is not executing
return MaterialApp(
title: 'My Poor App',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color(0xff29c17e),
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: authProvider.isAuthenticated ? HomeScreen() : LoginScreen(),
onGenerateRoute: Router.onGenerateRoute,
);
);
LoginScreen.dart
class LoginScreen extends StatelessWidget
@override
Widget build(BuildContext context)
final authProvider = Provider.of<AuthProvider>(context, listen: false);
return Scaffold(
body: Center(
child: MaterialButton(
onPressed: () async
await authProvider.emailLogin('user@email.com', 'pass');
,
child: Text('Login'))),
);
HomeScreen.dart
class HomeScreen extends StatelessWidget
@override
Widget build(BuildContext context)
final auth = Provider.of<AuthProvider>(context, listen: false);
return Scaffold(
body: Center(
child: MaterialButton(
elevation: 2,
onPressed: ()
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryScreen()));
,
child: Text('Reset')),
),
);
AuthProvider.dart
class AuthProvider extends ChangeNotifier
bool _isAuthenticated = false;
bool get isAuthenticated => _isAuthenticated;
set isAuthenticated(bool isAuth)
_isAuthenticated = isAuth;
notifyListeners();
Future emailLogin(String email, String password) async
isAuthenticated = true;
Future logout() async
isAuthenticated = false;
如果我使用Provider.of<AuthProvider>(context).logout()
从主页注销它可以正常工作。但是,如果我 push
或 pushReplacement
一条新路线并尝试从新路线注销(只是说我从主页导航到类别页面并尝试从那里注销),我不会被重定向到 LoginPage。如果我打印 isAuthenticated
的值,它会打印 false 但消费者没有在听,或者至少没有对变量更改做出反应。
请不要将此问题标记为重复,我已经搜索了许多其他类似的问题,但没有一个适合我的情况。
编辑: CategoryScreen.dart
class CategoryScreen extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: ()
final auth = Provider.of<AuthProvider>(context, listen: false);
auth.logout();
// print(auth.isAuthenticated);
,
child: Text('Category Logout'),
),
),
);
【问题讨论】:
我猜问题出在你的Navigator
。当您从Category
注销时,请在注销后使用Navigator.pushAndRemoveUntil 或Navigator.pushNamedAndRemoveUntil
@Alok 已经检查过了,但是没有用。
只有当您尝试从 CategoryPage
注销时,您是否停留在同一页面?
@Alok 。是的,我使用导航器推送并尝试从那里注销的所有其他页面,它只是保持静止。消费者根本没有反应。而且我在控制台中没有任何错误。
查看答案 Suraj。我希望这对你有用 :) 让我知道,否则,我们会寻找其他一些变化。但我已经给了你更大的图景
【参考方案1】:
我猜你的问题是你没有在logout
中使用Consumer
,在home
中MaterialApp
。看看,如果它适合你
main.dart
// needs to listen to the changes, to make changes
home: Consumer<AuthProvider>(
builder: (context, authProvider, child)
return authProvider.isAuthenticated ? HomeScreen() : LoginScreen();
)
由于您的home
不存在Consumer
,因此即使更改了值,它也无法按照提供者为您更新视图。
【讨论】:
消费者小部件下的相同登录页面或主页被导航器直接推送到MaterialApp下方的新页面替换。现在我在树中丢失了消费者小部件。 将您的消费者用于Home
,而不是MaterialApp
@SurajKhanal
完全实现为您的答案。以上是关于提供者登录注销颤动的主要内容,如果未能解决你的问题,请参考以下文章