1.6、Mixins
在 Dart 中支持混入的模式,如下图所示,混入时的基础顺序是从右到左依次执行的,而且和 super 有关,同时 Dart 还支持 mixin 关键字的定义。
Flutter 的启动类用的就是 mixins 方式
1.7、isolate
Dart 中单线程模式中增加了 isolate 提供跨线程的真异步操作,而因为 Dart 中线程不会共享内存,所以也不存在死锁,从而也导致了 isolate 之间数据只能通过 port 的端口方式发送接口,类似于 Scoket 的方式,同时提供了 compute 的封装接口方便调用。
1.8 call
Dart 为了让类可以像函数一样调用,默认都可以实现 call() 方法,同样 typedef 定义的方法也是具备 call() 条件。
比如我定义了一个 CallObject
就可以通过以下执行
然后我定义了
就可以通过直接执行和判空执行处理
2、Flutter 中常见的
2.1、ChangeNotifier
如下图所示, ChangeNotifier 模式在 Flutter 中是十分常见的,比如 TextField 控件中,通过 TextEditingController 可以快速设置值的显示,这是为什么呢?
如下图所示,这是因为 TextEditingController 它是 ChangeNotifier 的子类,而 TextField 的内部对其进行了 addListener,同时我们改变值的时候调用了 notifyListener,触发内部 setState。
2.2、InheritedWidget
在 Flutter 中所有的状态共享都是通过它实现的,如自带的 Theme , Localizations ,或者状态管理的 scoope_model 、 flutter_redux 等等,都是基于它实现的。
如下图是 SliderTheme 的自定义实现逻辑,默认 Theme 中是包含了 SliderTheme,但是我们可以通过覆盖一个新的 SliderTheme 嵌套去实现自定义,然后通过 SliderThemetheme=SliderTheme(context); 获取,其中而 context 的实现就是 Element。
在 Element 的 inheritFromWidgetOfExactType 方法实现里,有一个 Map< Type,InheritedElement>_inheritedWidgets 的对象。
_inheritedWidgets 一般情况下是空的,只有当父控件是 InheritedWidget 或者本身是 InheritedWidgets 时才会有被初始化,而当父控件是 InheritedWidget 时,这个 Map 会被一级一级往下传递与合并 。
所以当我们通过 context 调用 inheritFromWidgetOfExactType 时,就可以往上查找到父控件的 Widget 。
2.3、StreamBuilder
StreamBuilder 一般用于通过 Stream 异步构建页面的,如下图所示,通过点击之后,绿色方框的文字会变成 addNewxxx,因为 Stream 进行了 map 变化,同时一般实现 bloc 模式的时候,经常会用到它们。
类似的还有 FutureBuilder
2.4、State 中的参数使用
一般 Widget 都是一帧的,而 State 实现了 Widget 的跨帧绘制,一般定义的时候,我们可以如下图一样实现,而如下图尖头所示,这时候我们点击 setState 改变的时候,是不会出现效果的,为什么呢?
其实 State 对象的创建和更新时机导致的:
1、createState 只在 StatefulElement 创建时才会被创建的。
2、StatefulElement 的 createElement 一般只在 inflateWidget 调用。
3、updateChild 执行 inflateWidget 时, 如果 child 存在可以更新的话,不会执行 inflateWidget。
3、四棵树
Flutter 中主要有 Widget 、 Element 、 RenderObject 、 Layer 四棵树,它们的作用是:
Widget :就是我们平常写的控件, Flutter 宇宙中万物皆 Widget ,它们都是不可变一帧,同时也是被人吐槽很多的嵌套模式,当然换个角度,事实上你把他当作 Widget 配置文件来写或者就好理解了。
Element :它是 BuildContext 的实现类, Widget 实现跨帧保存的 state 就是存放在这里,同时它也充当了 Widget 和 RenderObject 之间的桥梁。
RenderObject :它才是真正干活(layout、paint)等,同时它才是真实的 “dom” 。
Layer :一整块的重绘区域(isRepaintBoundary),决定重绘的影响区域。
skia 在绘制的时候, saveLayer 是比较消耗性能的,比如透明合成、 clipRRect 等等都会可能需要 saveLayer 的调用, 而 saveLayer 会清空 GPU 绘制的缓存,导致性能上的损耗,所以开发过程中如果掉帧严重,可以针对这一块进行优化。
评论