zoukankan      html  css  js  c++  java
  • Flutter 状态管理

    使用provider管理简单的状态

    加入依赖:

    #数据共享组件 https://github.com/rrousselGit/provider/blob/master/resources/translations/zh-CN/README.md
    provider: 6.0.1
    

    首先创建一个简单的实体类:

    class User{
      ///用户名
      String username;
      ///凭证
      String accessToken;
    
      User({required this.username, required this.accessToken});
    
    }
    

    ChangeNotifier

    用于向监听器发送通知

    在修改完相应的状态并且需要更新UI的时候,需要调用notifyListeners();这个方法。

    创建实体类对应的Notifier:

    class UserNotifier extends ChangeNotifier {
      User _user = User(username: '', accessToken: '');
    
      ///设置用户信息
      set user(User value) {
        _user = value;
        notifyListeners();
      }
    
      ///获取用户信息
      User get user => _user;
    
      ///退出登录
      void logout() {
        _user.username = '';
        _user.accessToken = '';
        notifyListeners();
      }
    }
    

    ChangeNotifierProvider

    ChangeNotifierProvider组件可以向其子孙结点暴露ChangeNotifier的一个实例

    需要放置在使用状态管理的最上层组件之上

    通常放在MyApp上面,用于管理全局状态:

    runApp(
        ChangeNotifierProvider(
          create: (BuildContext context) => UserNotifier(),
          child: const MyApp(),
        )
    );
    

    这里的UserNotifier只会被实例化一次

    如果想提供更多的状态,可以使用MultiProvider:

    void main() {
      runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (context) => CartModel()),
            Provider(create: (context) => SomeOtherClass()),
          ],
          child: const MyApp(),
        ),
      );
    }
    

    Consumer

    用于调用Notifier,在需要使用状态管理组件的外层包裹

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: const Text("登录"),
        ),
        body: Center(
          child: Consumer<UserNotifier>(builder: (BuildContext context, user, child) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Consumer<UserNotifier>(builder: (BuildContext context, user, child) {
                  return Text(user.user.username == '' ? '未登录' : user.user.username);
                }),
                const SizedBox(
                  height: 10,
                ),
                ElevatedButton(
                    onPressed: () {
                      user.logout();
                    },
                    child: const Text("注销"))
              ],
            );
          }),
        ),
      );
    }
    

    需要使用泛型指定要访问的模型类型:Consumer<UserNotifier>

    第二个参数user就是UserNotifier的实例

    第三个参数用于优化,如果Consumer下面有一个庞大的子树,不需要根据状态改变,就可以在child中创建一次,然后通过builder获取该child,放到相应的位置:

    return Consumer<CartModel>(
      builder: (context, cart, child) => Stack(
        children: [
          // Use SomeExpensiveWidget here, without rebuilding every time.
          if (child != null) child,
          Text("Total price: ${cart.totalPrice}"),
        ],
      ),
      // Build the expensive widget here.
      child: const SomeExpensiveWidget(),
    );
    

    Provider.of

    有的时候你不需要模型中的 数据 来改变 UI,但是你可能还是需要访问该数据。比如,ClearCart 按钮能够清空购物车的所有商品。它不需要显示购物车里的内容,只需要调用 clear() 方法。

    我们可以使用 Provider.of,并且将 listen 设置为 false

    Provider.of<CartModel>(context, listen: false).removeAll();
    

    在 build 方法中使用上面的代码,当 notifyListeners 被调用的时候,并不会使 widget 被重构。

    本文来自博客园,作者:Bin_x,转载请注明原文链接:https://www.cnblogs.com/Bin-x/p/15538876.html

  • 相关阅读:
    shiro学习详解(开篇)
    好记性不如烂笔头之Maven使用小记
    【转】log4j.properties文件的配置
    undefined和NUll的区别
    select选择框在谷歌火狐和IE样式的不同
    windows.onload和 document.ready区别
    深入理解line-height
    display:none,overflow:hidden,visibility:hidden之间的区别
    diplay:table-cell和伪元素:after方法让图片居中
    弹性布局各种坑爹兼容
  • 原文地址:https://www.cnblogs.com/Bin-x/p/15538876.html
Copyright © 2011-2022 走看看