
FlutterDojo设计之道——状态管理之路
Flutter万物皆Widget的理念很容易搭建出这样一个WidgetTree。
在这个Widget Tree中,通常会存在很多组件之间的相互依赖,时间一长,就很容易变成下面这样。
这是申明式编程的通病,因为Widget用于展示数据,而数据可能来源于很多其它的Widget,这时候跨Widget共享数据、传递数据,就变得很麻烦,而且不容易管理。
所以,Flutter在StatelessWidget、StatefulWidget的基础之上,还有一个InheritedWidget,专门用于进行数据、状态的共享与传递,除此之外,申明式编程独特的响应式架构,也通过观察者模式,让数据状态改变的监听变得比较容易,这些都是Flutter处理数据的优势。
下面的文章,将带领大家梳理Flutter中的数据流向,掌握Flutter的状态管理方案。
开篇
要管理Widget的数据、状态,首先要了解下,在Flutter中有哪些需要管理数据的场景。
一般来说,数据管理有两个场景:
同页面跨Widget数据管理
跨页面数据管理
Flutter在同一个Page中,可能存在很多的不同的Widget,这些Widget都在同一个Page层级之下,当某个Widget的状态发生改变之后,需要让其它Widget响应。
另外一种,就是多页面之间的数据共享。
那它们的区别是什么呢,在同一个Page下,所有的Widget与Page根Widget是可以形成父子关系的,因为通过PageRoute产生的新页面,其Page根Widget是挂载到App根Widget上的,多个Page之间的Widget,不存在父子关系。
首先,我们先来看下同页面跨Widget数据管理。
为了保证文章的完整性,本文会由浅入深,依次讲解Flutter中状态管理的方方面面,所以有些冗余的地方,请不要介意。
方案1-1 :StatefulWidget
这个相信大家都很了解了,StatefulWidget通过State来保存状态,当调用setState函数之后,整个StatefulWidget会重新执行build函数,从而使用全新的数据,生成新的Widget,这样看来,有了StatefulWidget之后,是不是就可以完全实现同页面的数据管理了呢?
的确可以,但是有个问题,如果页面里面有100个Widget,数据发生改变后,只有一个Widget需要接受这个改变,修改自己的UI,但是在这个StatefulWidget中,由于调用了setState函数,所以这个页面中的100个Widget都将执行重建,这显然是「家里有矿系列」,所以为了避免这个问题,就需要缩小StatefulWidget的范围,让setState函数控制的刷新,尽可能的范围小,这样当100个Widget中只有一个需要重建时,就不需要重新创建那99个不需要的Widget了。
但是新的问题又来了,StatefulWidget的范围小了,发生在这个StatefulWidget之外的数据改变,如何让这个StatefulWidget进行刷新呢?这时候,就需要利用到Flutter的响应式编程架构了。
方案1-2:ValueNotifier
从ValueNotifier的注释就能看明白,ValueNotifier实际上实现了一个观察者模式,ValueNotifier会持有一个Value对象,当Value对象发生改变时,即会通知到所有注册过的观察者。
那么借助ValueNotifier,就可以实现同Page内跨Widget的数据管理,将需要管理的数据托管给ValueNotifier,所有需要因为该数据而改变的Widget,都会注册监听,那么在数据发生改变时,ValueNotifier将自动通知到所有监听者,从而实现数据的管理。
下面这个例子,就演示了一个最简单的ValueNotifier的使用。
NotifierWidget注册了对ValueNotifier的监听,当Demo页面中的其它Widget触发了ValueNotifier的更新的时候(RaisedButton触发),NotifierWidget会自动接受到通知,从而刷新UI。
代码位置:Flutter Dojo-Widget-Async-ValueNotifier
自定义ValueNotifier
ValueNotifier同样可以指定自定义类型,其原理与使用基础类型是一样的。
同样是点击RaisedButton后,改变ValueNotifier.value的值,从而修改UI。
代码位置:Flutter Dojo-Widget-Async-ValueNotifier
通过ValueNotifier,我们将每个可能因为共享数据的变化而改变的Widget,封装起来,从而在数据改变的时候,只更新监听了该数据的Widget。
但是大家有没有发现,在使用ValueNotifier的时候,是有些冗余的,就好像前面用到的NotifierWidget,实际上大部分的ValueNotifier都需要这样配合使用,所以,Flutter也提供了这样一个类似的Widget——ValueListenableBuilder。
1-3:ValueListenableBuilder
ValueListenableBuilder正是这样一个Widget,它封装了对ValueNotifier的使用,简化了其创建过程,Flutter Dojo的首页上,PageView和下面的进度条保存同步的过程,就是通过ValueListenableBuilder来实现的。
代码位置:Flutter Dojo-/pages/main/mainpage_scroll_container.dart
ValueListenableBuilder的使用范式非常简单,即在多个创建修改、监听修改的Widget上,通过ValueNotifier来共享管理数据。
由于ValueListenableBuilder是一个StatefulWidget,所以它们的父Widget可以直接使用StatelessWidget来组织Widget,一个简单的示例如下所示。
代码位置:Flutter Dojo-Widget-Async-ValueListenableBuilder
作者:xuyisheng
来源:掘金
