Flutter示例系列(二)之状态管理-壹(scoped_model)

开发环境:
Mac OS 10.14.5
VSCode 1.36.1
Flutter 1.7.8+hotfix4

前言

Flutter示例系列(一)中,每点击一次加号,则执行一次加1方法,并且调用 setState() 方法更新UI。

但是如果是一个大型应用,页面比较多,状态也比较多,有时还会出现多个页面共用同一个状态,此时页面刷新和状态管理略显复杂。所以需要 scoped_model 来替我们管理状态,显得更加方便。

概念

scoped_model :父类向后代传递数据模型,每当数据模型更新,使用过模型的子类都会重建。

提供三个主要类:

  1. Model 类。继承 Model 创建自己的模型类,可以监听模型类的改变。
  2. ScopeModel 组件。如果需要在组件层次中深入传递 model ,可以将 model 包在ScopeModel 组件中,这样子组件都可以使用。
  3. ScopeModelDescendant 组件。用此组件在 widget树中 找到合适的 ScopeModel。当 Model 通知改变时,它会自动重建。

探索

Flutter示例系列(一)中,我们已创建好项目,现在我们稍作修改:
1.添加依赖

scoped_model: ^1.0.1

2.创建自己的CounterModel类

import 'package:scoped_model/scoped_model.dart';

class CounterModel extends Model {
  int _counter = 0;

  //get方法,获取_counter值
  int get counter => _counter;

  //每次调用,_counter 加1
  void increment() {
    _counter ++;

    //通知所有的监听类,数据改变
    notifyListeners();
  }
}

3.修改main.dart文件

a)在 MyApp 类中,定义构造方法,参数是 CounterModel 类型,用于传递CounterModel对象

//自定义构造方法,@required 表明调用时必须有参数
  const MyApp({Key key, @required this.model}) : super(key: key);

b)在 MyApp 类中,定义 CounterModel 类型的实例变量,用于接收从根widget处传递的model

//定义model变量
  final CounterModel model;

c)在 MyApp 类中,build() 函数返回 ScopedModel 组件,并传递model

return ScopedModel<CounterModel> (
      model: model, 
      child: MaterialApp(
        title: 'Scoped Model Demo',
        home: MyHomePage(title: 'Scoped Model Demo'),
      ),
    );

d)在MyHomePage中,修改类继承自StatelessWidget

class MyHomePage extends StatelessWidget

e)在MyHomePage中,利用ScopedModelDescendant获取model

ScopedModelDescendant<CounterModel> (
              //当model更新时调用
              builder: (context, child, model){
                return Text(
                  model.counter.toString(),
                  style: Theme.of(context).textTheme.display1,
                );
              },
            )

或者这样获取

final counterModel = ScopedModel.of<CounterModel>(context, rebuildOnChange: true);

思考?

如何在一个 build() 监听多个models?

比如我们不让AppModel包含了所有应用逻辑,而是分成UserModel、SearchModel、ProductModel等。

然而,我们需要在一个Widget中获取其中两个model,有两种选择:
1.用多个ScopedModelDescendant
2.用多个ScopedModel.of(),无需管理订阅,Flutter通过 InheritedWidgets去处理

class CombinedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final username =
      ScopedModel.of<UserModel>(context, rebuildOnChange: true).username;
    final counter =
      ScopedModel.of<CounterModel>(context, rebuildOnChange: true).counter;

    return Text('$username tapped the button $counter times');
  }
}
//注意:直接使用第二种时,rebuildOnChange设置非常重要!

总结

至此,大致了解Scoped_model是如何集成项目中,但是一个成熟的项目,远比示例复杂,由浅及深,多查阅资料。
下一篇将会讲解fish-redux的用法。

本文Demo地址

碎碎念:
一开始觉得状态管理差不多也是redux_xxx之类,但是网上查阅之后,才知道原来有好几种管理方式,包含scoped_model、BLoC等。
大家也可以查看参考博文,原博主讲的更加详细(竖大拇指?)。
scoped_model地址
参考博文
原始示例

=================================================================
个人博客
Github
个人公众号:Flutter小同学
个人网站

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值