Flutter _ 状态管理探索篇,2021Android开发社招面试总结

这里我们以一个最简单的CountApp举例,详细介绍Scoped_model的用法。该项目完整代码已放在github仓库

这是一个在不同页面使用Scoped共享状态信息的app。这两个页面都依赖于一个数字,这个数字会随着我们按下按钮的次数而增加。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ujk83uiI-1630663346547)(https://user-gold-cdn.xitu.io/2018/9/11/165c864da39b5296?imageslim)]

第一步:添加依赖

在pubspec中添加scoped_model的依赖。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fFNMPAV4-1630663346549)(https://user-gold-cdn.xitu.io/2018/9/17/165e7f1aa9eb35e3?imageView2/0/w/1280/h/960/ignore-error/1)]

第二步:创建Model

在Scoped中,Model是一个只包含与状态相关信息的单位。我们应该把状态数据与操作数据的方法抽象出来封装到Model中。

import 'package:scoped_model/scoped_model.dart';

class CountModel extends Model{
  int _count = 0;
  get count => _count;
  
  void increment(){
    _count++;
    notifyListeners();
  }
} 
  • 我们需要让我们自定义的CountModel继承至Model。
  • 在状态发生变化时(increment)通知所有用到了该model的子项更新状态。(notifyListeners)

第三步:将Model放入顶层

//创建顶层状态
  CountModel countModel = CountModel();

  @override
  Widget build(BuildContext context) {
    return ScopedModel<CountModel>(
      model: countModel,
      child: new MaterialApp(
        home: TopScreen(),
      ),
    );
  } 
  • 我们在顶层创建了一个CountModel的实例。
  • ScopedModel是一个StatelessWidget,它接收一个model,并提供给需要它的所有部件。
  • 将ScopedModel的model属性绑定我们的CountModel对象。

第四步:在子页面中获取Model

我们可以从前面的演示图片中看出,一共有两个页面,都使用了同一个model。 Scoped_model提供了两种方式在子页面中获取model。我们先来介绍第一种,使用ScopedModelDescendant获取model。

@override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<CountModel>(
      builder: (context,child,model){
        return Scaffold(
          body: Center(
            child: Text(
              model.count.toString(),
              style: TextStyle(fontSize: 48.0),
            ),
          ),
        );
      },
    );
  } 
  • ScopedModelDescendant是一个Stateless Widget,它接收三个参数。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBqwxlLA-1630663346550)(https://user-gold-cdn.xitu.io/2018/9/17/165e8034b2584374?imageView2/0/w/1280/h/960/ignore-error/1)]

  • builder是一个ScopedModelDescendantBuilder,它接收三个参数。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-373JEsJZ-1630663346552)(https://user-gold-cdn.xitu.io/2018/9/17/165e80f4c271a7b1?imageView2/0/w/1280/h/960/ignore-error/1)]

    ,在builder中能够通过model来获取CountModel实例。

  • rebuildOnChange属性能够控制当该状态发生变化时,是否rebuild,作用等同于setState。也就是说我们调用改变状态的一些方法时,不必再setState。

floatingActionButton: new FloatingActionButton(
          onPressed: () => model.increment(),
          tooltip: 'Increment',
          child: new Icon(Icons.add),
        ) 

第二种获取model的方式——使用ScopedModel.of

final countModel = ScopedModel.of<CountModel>(context);
countModel.increment(); 

或者在Model中重写of方法

class CountModel extends Model{
  int _count = 0;
  get count => _count;

  void increment(){
    _count++;
    notifyListeners();
  }
//重写of方法
  CountModel of(context) =>
      ScopedModel.of<CountModel>(context);
} 

然后直接通过CountModel获取model实例

final countModel2 = CountModel().of(context); 

这种方式似乎让我们的代码有更好的可阅读性。

【注意:】我们在使用第二种方式的时候,rebuildOnChange属性默认为false,所以会导致无法刷新(同步)状态的情况发生,需要手动指定rebuildOnChange:true。这里要非常感谢@荣毅coolboy同学的分享!

Q&A

这里看上去似乎只添加了一个model,我应该如何添加多个model

要解决这个问题很简单,使用Mixin!

class MainModel extends Model with AModel,BModel,CModel{} 

然后将MainModel放在顶层即可。 这里有一个比较完整的使用ScopedModel管理状态的应用,详细用法可参考该项目。

Scoped是如何做到同步不同页面中的状态的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZjIakVHX-1630663346554)(https://user-gold-cdn.xitu.io/2018/9/17/165e82557e8565e8?imageView2/0/w/1280/h/960/ignore-error/1)]

Model实现了Listenable接口,并重写了void addListener(VoidCallback listener),removeListener(VoidCallback listener)方法,实现了观察者模式。 每当我们调用notifyListeners()方法时,将会通知观察者更新状态。

Scoped如何做到数据能够互相共享的

在不同页面间的数据传递使用了InheritedWidget。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WQWIDbuz-1630663346555)(https://user-gold-cdn.xitu.io/2018/9/18/165e856263e9d6b2?imageView2/0/w/1280/h/960/ignore-error/1)]

模式。 每当我们调用notifyListeners()方法时,将会通知观察者更新状态。

Scoped如何做到数据能够互相共享的

在不同页面间的数据传递使用了InheritedWidget。

[外链图片转存中…(img-WQWIDbuz-1630663346555)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[2\]提到,Flutter_blue只兼容Android SDK的19版本及以上。因此,如果你想在Android上使用flutter_blue,你需要在android/app/build.gradle文件中更改相应的配置。具体的更改步骤可以参考该引用内容中的说明。 另外,引用\[3\]提到,要了解如何使用flutter_blue_plus,最好的方法是查阅文档或者查看flutter_reactive_ble库的代码。你可以从flutter_reactive_ble库的example目录下的示例代码开始,逐步学习如何使用flutter_blue_plus。在示例代码中,可以看到在main.dart文件中创建了一个名为FlutterBlueApp的根组件。通过运行该组件,你可以开始使用flutter_blue_plus库。 #### 引用[.reference_title] - *1* *3* [Flutter蓝牙框架-flutter_blue_plus使用及源码解析](https://blog.csdn.net/Yaoobs/article/details/131570861)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [flutter_blue](https://blog.csdn.net/weixin_31865445/article/details/117817409)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值