提供者登录注销颤动

Posted

技术标签:

【中文标题】提供者登录注销颤动【英文标题】:Provider login logout flutter 【发布时间】:2020-12-06 20:27:23 【问题描述】:

我正在尝试使用 Provider 创建一个简单的身份验证流程。我有三页:

    登录页面 入职页面 主页

这个应用的流程是:

    如果用户第一次打开应用程序,他/她将被重定向到入门,然后登录到主页。 对于第二次用户,应用首先检查登录状态并重定向到登录 -> 主页或直接到主页。

这是我在代码中的设置:

ma​​in.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&lt;AuthProvider&gt;(context).logout() 从主页注销它可以正常工作。但是,如果我 pushpushReplacement 一条新路线并尝试从新路线注销(只是说我从主页导航到类别页面并尝试从那里注销),我不会被重定向到 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,在homeMaterialApp。看看,如果它适合你

ma​​in.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 完全实现为您的答案。

以上是关于提供者登录注销颤动的主要内容,如果未能解决你的问题,请参考以下文章

如何在颤动中自动注销firebase用户?

颤动的firebase身份验证提供者未通知

从外部提供者注销后,身份服务器登录流程卡住

如何在颤动中自动登录现有用户

开放标识。你如何注销

Django 无法显示提供的注销模板