Flutter 提供者状态管理、注销概念

Flutter provider state management, logout concept

我正在尝试为我的应用程序实施自定义注销解决方案,无论用户当前身在何处,单击 Logout button 后,应用程序将导航回 Login page

我的想法是,与其监听每个组件的状态变化,不如在主组件上设置一个监听器 -> MyApp.

为了简单起见,我将项目精简到最低限度。这是我的个人资料 class 的样子:

class Profile with ChangeNotifier {
  bool _isAuthentificated = false;
  bool get isAuthentificated => _isAuthentificated;
  set isAuthentificated(bool newVal) {
    _isAuthentificated = newVal;
    notifyListeners();
  }
}

现在,在 Main 下,我已将此提供商注册如下:

void main() => runApp(
      MultiProvider(
        providers: [
          ChangeNotifierProvider(
            create: (_) => Profile(),
          )
        ],
        child: MyApp(),
      ),
    );

最后 MyApp 组件:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return Consumer<Profile>(
      builder: (context, profile, _) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            brightness: Brightness.light,
            primaryColor: Color.fromARGB(255, 0, 121, 107),
            accentColor: Color.fromARGB(255, 255, 87, 34),
          ),
          home: buildBasePage(context, profile),
        );
      },
    );
  }

  Widget buildBasePage(BuildContext context, Profile currentProfile) {
    return !currentProfile.isAuthentificated
        ? LoginComponent()
        : MyHomePage(title: 'Flutter Demo Home Page test');
  }
}

我的想法是,由于 MyApp 组件是 master,我应该能够创建一个消费者,如果当前用户通过身份验证,它会收到通知,并会做出相应的回应。

发生的事情是,当我在例如MyHomePage 组件,然后单击 Logout() 方法,如下所示:

  void _logout() {
    Provider.of<Profile>(context, listen: false).isAuthentificated = false;
  }

我希望在更改 属性 后,初始 MyApp 组件会做出反应并生成 LoginPage;事实并非如此。我尝试将 Consumer 更改为 Provider.of<Profile>(context, listen: false),但结果相同。

为了使这个概念起作用,我需要做什么?这样做是否正确?

我的意思是我肯定可以在某种程度上更新我的 Profile class,我添加以下方法:

  logout(BuildContext context) {
    _isAuthentificated = false;

    Navigator.push(
        context, MaterialPageRoute(builder: (context) => LoginComponent()));
  }

然后简单地调用 Provider.of<Profile>(context, listen: false).logout(),但是我认为 Provider 包是为此设计的...还是我遗漏了什么?

如能提供有关此事的任何帮助,我们将不胜感激。

您无需传递 listen:false,只需调用

Provider.of<Profile>(context).logout()

所以你的个人资料 class 看起来像

      class Profile with ChangeNotifier {
  bool isAuthentificated = false;


  logout() {
    isAuthentificated = false;
    notifyListeners();
  }
}

我不知道为什么它不适合你。这是我根据您的描述构建的完整示例。有效!

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Profile with ChangeNotifier {
  bool _isAuthentificated = false;

  bool get isAuthentificated {
    return this._isAuthentificated;
  }

  set isAuthentificated(bool newVal) {
    this._isAuthentificated = newVal;
    this.notifyListeners();
  }
}

void main() {
  return runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider<Profile>(
          create: (final BuildContext context) {
            return Profile();
          },
        )
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(final BuildContext context) {
    return Consumer<Profile>(
      builder: (final BuildContext context, final Profile profile, final Widget child) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(primarySwatch: Colors.blue),
          home: profile.isAuthentificated ? MyHomePage() : MyLoginPage(),
        );
      },
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(final BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Home [Auth Protected]")),
      body: Center(
        child: RaisedButton(
          child: const Text("Logout"),
          onPressed: () {
            final Profile profile = Provider.of<Profile>(context, listen: false);
            profile.isAuthentificated = false;
          },
        ),
      ),
    );
  }
}

class MyLoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Login")),
      body: Center(
        child: RaisedButton(
          child: const Text("Login"),
          onPressed: () {
            final Profile profile = Provider.of<Profile>(context, listen: false);
            profile.isAuthentificated = true;
          },
        ),
      ),
    );
  }
}