作者:Nayuta 链接:https://juejin.im/post/6868104488109604871 本文由作者授权发布。
Flutter开发中,大家都绕不开Widget的刷新,setState()是最简单的用法。但随着当app的交互变得复杂,setState出现的次数便会显著增加,每次setState都会重新调用build方法,这势必对于性能以及代码的可阅读性带来一定的影响。如何优雅的解决这个问题,不得不提到StreamBuilder,StreamBuilder是Flutter中异步构建的核心组件。许多著名的开源框架例如Bloc皆是基于此实现。如果StreamBuilder有了解可以直接看第二部分
现在页面上有两个数字key1和key2需要展示,当点击上方的按钮时,我们对应修改key1或者key2的值。
img
采用setState()的方式,我们知道很简单,建立本地变量key1,key2,然后放入对应的Text中直接展示。当我们点击按钮时使本地变量key1,key2做增加操作,之后调用setState()。
img
img
img
img
但当我刷新Key1的时候, 会同时重构Key2展示的两个Text,即使我的key2没有发生变化,显然这不是一种合理的做法。
其实Flutter中还提供了一个强大组件SteamBuilder来协助我们处理控件的刷新构建。
如图,是StreamBuilder使用基本结构,StreamBuidler基于dart中的异步核心之一Stream,采取观察者模式,发送方通过StreamControll发送数据,观察对象接收到数据后构建自己的内容。
从代码可知StreamBuilder接受两个参数,一个stream,表示我们监听的Stream(一个StreamBuilder监听一个Stream,但是一个Stream能被多个Widget监听),builder中传入我们需要构建的contentWidget。
这样Widget的构建完全由Stream触发,控件无需自行setState,它的构建完全由数据驱动,是一种响应式编程。也是许多开源框架例如Bloc等核心原理。
回到上面的例子中,当我们采用StreamBuilder后,上面的例子就变得非常的清晰了,我们建立两条StreamControler,然后把图中的展示key1和key2的两组Text分别由两个StreamBuilder包裹。
在key1的点击事件中往Stream中add数据,这样在key1的流上产生了一条数据,对应的监听者收到数据后,只更新自己的内容,不会重建其他区域。
经过上面的了解,我们知道。StreamBuilder可以完美解决局部刷新的问题,但StreamBuilder也有着同样明显的缺点,使用起来非常麻烦,需要自己手动创建流,将控件用StreamBuilder包裹构造。
当我们的页面需要多个局部刷新的时候,Stream的编写将会非常麻烦。类似Provide的解决方案也需要设定顶级Widget,然后用consumer包裹子控件,调用更新等等操作。
有没有什么方式可以简化我们的使用呢?
我们注意到,StreamBuilder需要监听一个stream,而这个stream往往来自StreamControler。对于每个StreamControler来说,就像生活中的一条 一对多的数据线数据线(DataLine)一样。
对于这条DataLine,最核心的有两个方法
1、添加观察者(通过StreamBuilder包裹实际展示的contentWidget) : 类似数据线连接手机
2、发送数据 :类似通过数据线给手机充电(因为是一对多的过程)
基于这种思路,设计了一个SingleDataLine,对于这条“数据线"而言,其中T约束了这条线的使用数据类型,currentData能帮助我们拿到当前最新的数据,setData(T t)发送数据。
核心在于我们的addObserver中,该方法需要传入一个 返回值为Widget Function(BuildContext context, T data) observer的方法,这个传入的方是我们需要构建的Widget的构造方法。
这个addObserver方法返回一个DataObserverWidget控件,这个组件就是帮我们对StreamBuilder进行了封装,以此简化StreamBuilder的使用。
上面我们通过SingDataLine简化了StreamBuilder的使用,但当页面中有多个SingleDataLine的时候,对它的创建和管理,可能会成为一件麻烦的事儿。基于此设计了一个dataBus总线管理。
我们将每一个key和对应的DataLine存入Map中进行管理,通过直接调用getLine(key)的方法获取创建DataLine。而且由于MultDataLine是mixin定义,所以我们可以在任意的类中混入使用方法。例如直接在Widget中混入改类,调用getLine方法获取到StreamBuilder。
本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕,E-mail:xinmeigg88@163.com
本文链接:http://zleialh.tongchengxian.cn/news/3165.html
有话要说...