第七章 功能型组件
7.2 数据共享(InheritedWidget)
InheritedWidget
是Flutter中非常重要的一个功能型组件,它提供了一种数据在widget树中从上到下传递、共享的方式,比如我们在应用的根widget中通过InheritedWidget
共享了一个数据,那么我们便可以在任意子widget中来获取该共享的数据!这个特性在一些需要在widget树中共享数据的场景中非常方便!如Flutter SDK中正是通过InheritedWidget来共享应用主题(Theme
)和Locale (当前语言环境)信息的。
InheritedWidget
和React中的context功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据。InheritedWidget
的在widget树中数据传递方向是从上到下的,这和通知Notification
(将在下一章中介绍)的传递方向正好相反。
应该在didChangeDependencies()中做什么?
一般来说,子widget很少会重写此方法,因为在依赖改变后framework也都会调用build()
方法。但是,如果你需要在依赖改变后执行一些昂贵的操作,比如网络请求,这时最好的方式就是在此方法中执行,这样可以避免每次build()
都执行这些昂贵操作。
深入了解InheritedWidget
调用dependOnInheritedWidgetOfExactType()
和 getElementForInheritedWidgetOfExactType()
的区别就是前者会注册依赖关系,而后者不会,所以在调用dependOnInheritedWidgetOfExactType()
时,InheritedWidget
和依赖它的子孙组件关系便完成了注册,之后当InheritedWidget
发生变化时,就会更新依赖它的子孙组件,也就是会调这些子孙组件的didChangeDependencies()
方法和build()
方法。而当调用的是 getElementForInheritedWidgetOfExactType()
时,由于没有注册依赖关系,所以之后当InheritedWidget
发生变化时,就不会更新相应的子孙Widget。
那么,现在就带来了一个问题:实际上,我们只想更新子树中依赖了ShareDataWidget
的组件,而现在只要调用_InheritedWidgetTestRouteState
的setState()
方法,所有子节点都会被重新build,这很没必要,那么有什么办法可以避免呢?答案是缓存!一个简单的做法就是通过封装一个StatefulWidget
,将子Widget树缓存起来,具体做法下一节我们将通过实现一个Provider
Widget 来演示如何缓存,以及如何利用InheritedWidget
来实现Flutter全局状态共享。
7.3 跨组件状态共享(Provider)
在Flutter开发中,状态管理是一个永恒的话题。一般的原则是:如果状态是组件私有的,则应该由组件自己管理;如果状态要跨组件共享,则该状态应该由各个组件共同的父元素来管理。对于组件私有的状态管理很好理解,但对于跨组件共享的状态,管理的方式就比较多了,如使用全局事件总线EventBus(将在下一章中介绍),它是一个观察者模式的实现,通过它就可以实现跨组件状态同步:状态持有方(发布者)负责更新、发布状态,状态使用方(观察者)监听状态改变事件来执行一些操作。下面我们看一个登陆状态同步的简单示例:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!