1 背景介绍

1.1 声明式ui

声明式UI其实并不是近几年的新技术,但是近几年声明式UI框架非常的火热。单说移动端,跨平台方案有:RN、Flutter。iOS原生有:SwiftUI。android原生有:compose。可以看到声明式UI是以后的前端发展趋势。而状态管理是声明式UI框架的重要组成部分。

1.2 声明式UI框架的状态

在移动端之前的命令式UI框架,没有状态的概念。每个控件其实都是无状态的,我们要更新UI需要手动的去set。命令式UI引入状态的概念,状态可以理解为订阅了控件所依赖数据的变化,当一个控件依赖的数据发生变化时,自动刷新UI展示。最大的优势就是可以很方便的做到UI和逻辑的解耦。

2 provider状态管理

2.1 使用方式

定义一个页面如下:

实现功能,当点击“按钮”的时候,更新“你好”这个组件

页面部分代码实现(基于StatelessWidget实现):

model部分实现:

2.2 问题和不足

点击“按钮”的时候查看页面刷新,发现下表罗列的Widget都执行了刷新操作,使用Selector虽然被包裹的内容没有刷新,但是需要进行校验操作。

2.2.1 控件刷新

2.2.2 问题分析

  1. 使用不太灵活,想要消费事件刷新UI必须有顶层的Provider提供model,在一些复杂场景可能会增加逻辑复杂度
  2. 状态刷新,不能实现最小粒度的管理
  3. 代码不够简洁

3 新的状态管理方式实践

3.1 使用方式

实现同样的上述页面逻辑,代码如下(同样基于StatelessWidget实现):

首先不需要依赖外部的provider提供Model,任何想要独立刷新的区域使用TosObWidget控件包裹即可,使用比较灵活,我们可以把TosObWidget插入到任何我们想要的位置(包括provider内),代码逻辑比较简洁

model实现:

model的实现更加简洁,不需要继承ChangeNotifier,所以可以把状态数据定义在任何我们想要的地方,使用.tos扩展属性返回一个包含默认值的RxObj对象,当我们使用set方法更改RxObj的value的时候,通知依赖此对象的TosObWidget区域进行刷新,例:我们点击按钮的时候,_model.textA.value = “你好${_model.i++}”,执行后就会刷新依赖textA的TosObWidget(() => Text(_model.textA.value))区域

查看刷新状态(与provider对比):

对比发现TosObWidget这种方式,只有依赖的数据发生变化的TosObWidget才会更新状态,可以实现状态刷新粒度最小化,提高性能

3.2 设计思路

3.2.1 TosObWidget

首先是使用入口,定义一个TosObWidget控件,入参为build函数,返回widget,每个TosObWidget就是一个可独立进行状态刷新的区域

TosObWidget控件的实现如下:

TosObWidget的build函数为重载的其父类_ObzWidget的build函数,最终会被_ObzWidget的_ObzState调用,_ObzWidget的实现如下:

接下来查看_ObzState的实现,主要逻辑都在这个类进行实现,这里贴出所有的代码(注意框起来的逻辑):

3.2.2 TosObWidget逻辑分析

  1. 首先_ObzState依赖一个RxObserver _observer变量
  2. RxObserver _observer这个 变量持有了_updateUI()这个方法,最终会通过这个方法刷新TosOBWidget的状态
  3. 当TosObWidget执行build的时候,会通过一个静态变量RxObserver.proxy把_observer共享出去
  4. 这样TosObWidget包裹的内容,使用RxObj的getValue的时候会拿到被共享的_observer,这时建立RxObj和TosObWidget的联系
  5. 联系建立后,重置共享变量RxObserver.proxy
  6. 这样在RxObj的value执行set方法时,会调用到与其绑定的TosObWidget的_updateUI()这个函数

3.2.3 RxObj的实现

如下贴出RxObj的value的get和set函数:

  1. 当执行RxObj的value的get方法时,代码如下,拿到 RxObserver的静态成员变量proxy,类型为RxObserver(即为上一步TosObWidget共享出来的_observer)
  2. 判断RxObserver.proxy不为空,且没有被添加到_observers列表( List _observers),则添加
  3. 当执行RxObj的value的set方法时,校验value是否与当前的value值相同,且判断是否是首次创建(首次创建不会执行状态刷新)
  4. 校验完成后则赋值执行refresh()函数,更新TosObWidget的状态

refresh()函数的实现如下:

observer.update()函数即为执行与Rxobj关联的TosObWidget的_updateUI()函数:

看下RxObserver的实现:

注意框起来的逻辑,update函数即上面_ObzState的_updateUI()函数的引用

至此整个实现流程已经贯通了,接下来看下如何使用:

1)通过.tos扩展属性定义RxObj变量:

2).tos扩展属性的实现如下:

3)如果要创建一个默认值为空的,RxObj实例,使用如下方式:

此时如果我们使用RxObj的setValue方法,就会刷新依赖它的所有TosObWidget控件,如果有些情况下,没有调用setValue方法,但是需要刷新状态,可手动调用refresh()方法,实现如下:

至此,就完成了TosObWidget控件的状态刷新

4 总结

注:基于本文示例的功能逻辑进行对比

作者:京东物流 张俊飞

来源:京东云开发者社区

Flutter状态管理新的实践的更多相关文章

  1. Flutter 状态管理- 使用 MobX

    文 / Paul Halliday, developer.school 创始人 众所周知,状态管理是每个软件项目都需要持续迭代更新的方向.它并不是一个「一次性」的工作, 而需要不断确保你遵循的最佳实践 ...

  2. Flutter | 状态管理特别篇——Provide

    前言 今天偶然发现在谷歌爸爸的仓库下出现了一个叫做flutter-provide的状态管理框架,2月8日才第一次提交,非常新鲜.在简单上手之后感觉就是一个字--爽!所以今天就跟大家分享一下这个新的状态 ...

  3. Flutter 状态管理之BLoC

    在正式介绍 BLoC之前, 为什么我们需要状态管理.如果你已经对此十分清楚,那么建议直接跳过这一节.如果我们的应用足够简单,Flutter 作为一个声明式框架,你或许只需要将 数据 映射成 视图 就可 ...

  4. Flutter状态管理之provide和provider的使用区别

    说道状态管理不得不说谷歌的亲自开发的两款状态管理Widget:第一个是provide,第二个是provider. 这两个的区别就是一个出来的早,现在好像没整么更新了.第二个是2019才出来的目前的版本 ...

  5. Flutter状态管理Provider,简单上手

    在之前的文章中介绍了 Google 官方仓库下的一个状态管理 Provide.乍一看这俩玩意可能很容易就被认为是同一个东西,仔细一看,这不就差了一个字吗,有什么区别呢. 首先,你要知道的最大的一个区别 ...

  6. Flutter 状态管理 flutter_Provide

    项目的商品类别页面将大量的出现类和类中间的状态变化,这就需要状态管理.现在Flutter的状态管理方案很多,redux.bloc.state.Provide. Scoped Model : 最早的状态 ...

  7. Flutter实战视频-移动电商-24.Provide状态管理基础

    24.Provide状态管理基础 Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsour ...

  8. Flutter移动电商实战 --(24)Provide状态管理基础

    Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsourcetag=s_pcqq_aiom ...

  9. (转)flutter 新状态管理方案 Provide (一)-使用

    flutter 新状态管理方案 Provide (一)-使用     版权声明:本文为博主原创文章,基于CC4.0协议,首发于https://kikt.top ,同步发于csdn,转载必须注明出处! ...

  10. React 新 Context API 在前端状态管理的实践

    本文转载至:今日头条技术博客 众所周知,React的单向数据流模式导致状态只能一级一级的由父组件传递到子组件,在大中型应用中较为繁琐不好管理,通常我们需要使用Redux来帮助我们进行管理,然而随着Re ...

随机推荐

  1. 好饭不怕晚,Google基于人工智能AI大语言对话模型Bard测试和API调用(Python3.10)

    谷歌(Google)作为开源过著名深度学习框架Tensorflow的超级大厂,是人工智能领域一股不可忽视的中坚力量,旗下新产品Bard已经公布测试了一段时间,毁誉参半,很多人把Google的Bard和 ...

  2. 使用Kali复现永恒之蓝

    使用Kali复现永恒之蓝 本次实验为离线靶机测试 实验步骤 确认测试环境:在开始测试之前,需要确认测试环境是否符合要求.我使用的是一台运行Kali的测试机和一台运行Windows 7 64位的靶机.确 ...

  3. Mybatis 获取自增主键 useGeneratedKeys与keyProperty解答

    Mybatis 获取自增主键 31bafebb-a95b-4c35-a949-8bc335ec6e2e 今天开发的时候遇到一个疑惑,业务场景是这样的, 但是百度好久没有找到合适的解答,于是自己向同事了 ...

  4. [Java]算法练习:新农村建设

    1 题目描述 from 网友 CASE1 输入 A1 A8 输出 [A1,A2,A3,A4,A5,A6,A7,A8] CASE2 输入 A1 K1 输出 [A1,B1,C1,D1,E1,F1,G1,H ...

  5. [Linux]U盘启动盘安装CentOS7系统(LiveGNOME版)

    1 准备:工具 U盘 容量:视CentOS具体版本需要而定.推荐4G+ UltraISO(软碟通) ISO制作工具 / U盘启动盘刻录工具 2 制作:U盘启动盘 step1 下载CentOS镜像 Ce ...

  6. Spring Initailizr(项目初始化向导)

    本地创建 官网创建版 在Spring官网https://start.spring.io/ 中选择 此时这个项目以压缩包形式下载到本地文件中,然后解压,导入IDEA中 阿里start创建 如果国外的网址 ...

  7. tkinter的标签和按钮以及输入和文本

    一.标签和文本 import tkinter as tk #1.定义tk的实例对象,也就是窗口对象 window = tk.TK() #2.设置窗口大小无法缩小和放大 window.resiable( ...

  8. v-if与v-for的优先级

    在Vue2中 v-for的优先级要高于v-if 在Vue3中 v-if 的优先级要高于v-for

  9. 基础算法(排序 & 查找)

    快速排序.归并排序.整数二分查找.浮点数二分查找 快速排序 主要思想是分治: 确定分界点 调整范围 递归处理左右两段 代码: #include <iostream> using names ...

  10. Vue的项目打包为移动端(安卓手机应用)app

    现在基于vue全家桶技术体系,基本上可以开发各端的各种应用,pc端的应用,开发完成以后,直接运行打包命令 yarn build 即可打包,部署到服务器端上线即可.那么,今天我们来聊一聊,开发好的vue ...