引言
InheritedWidget,flutter中非常重要的一个功能组件。比如我们在应用的根 widget 中通过InheritedWidget共享了一个数据,那么我们便可以在任意子 widget 中来获取该共享的数据。
didChangeDependencies
说到 InheritedWidget ,我们不得不聊聊 state 对象中的 didChangeDependencies
方法。当子控件依赖使用了父控件中的 InheritedWidget,比如主题、locale(语言)等发生变化时,依赖其的子 widget 的didChangeDependencies
方法将会被调用。
一般来说,子 widget 很少会重写此方法,因为在依赖改变后 framework 也都会调用build()方法。但是,如果你需要在依赖改变后执行一些昂贵的操作,比如网络请求,这时最好的方式就是在此方法中执行,这样可以避免每次build()都执行这些昂贵操作。
重点: 如子控件build 方法中没有使用 InheritedShareWidget 的数据,那么它的didChangeDependencies
将不会被调用
如何使用?
我们简单用一个 count 自增的例子来记录 InheritedWidget 的使用:
- 新建 InheritedShareWidget 继承 InheritedWidget 作为共享数据源,以其为父节点提供子节点数据
import 'package:flutter/material.dart'; class InheritedShareWidget extends InheritedWidget { //用于共享的数据 final int data; InheritedShareWidget({this.data, Widget child}) : super(child: child); //定义便捷方法,方便子控件获取共享数据 static InheritedShareWidget of(BuildContext context) { ///当子控件依赖使用了我们的数据源时,数据变动会触发子控件中的 didChangeDependencies 方法 return context.dependOnInheritedWidgetOfExactType<InheritedShareWidget>(); ///(前提:子控件使用了数据源)子控件中的 didChangeDependencies 方法不会被触发 // return context.getElementForInheritedWidgetOfExactType<InheritedShareWidget>().widget; } @override bool updateShouldNotify(covariant InheritedShareWidget oldWidget) { //返回true时,才会通知子控件 return oldWidget.data != this.data; } }
注意:updateShouldNotify
方法中,通知指的是通知子控件的didChangeDependencies
方法,前提是子控件使用dependOnInheritedWidgetOfExactType
的方式获取共享数据。
- 子节点中如何获取共享数据?
class TestShareChildWidget extends StatefulWidget { const TestShareChildWidget({Key key}) : super(key: key); @override _TestShareChildWidgetState createState() => _TestShareChildWidgetState(); } class _TestShareChildWidgetState extends State<TestShareChildWidget> { @override void didChangeDependencies() { ///如build 方法中没有使用 InheritedShareWidget 的数据,那么它的didChangeDependencies()将不会被调用 super.didChangeDependencies(); print("enter didChangeDependencies"); } @override Widget build(BuildContext context) { print("enter child build"); //获取Inherited的共享数据: final data = InheritedShareWidget.of(context).data.toString(); return Text(data); } }
- 两者通过父子嵌套的关系联系在一起:
class _TestInheritedWidgetState extends State<TestInheritedWidget> { int count = 0; @override Widget build(BuildContext context) { return Center( child: InheritedShareWidget( data: count, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TestShareChildWidget(), RaisedButton( child: Text('add'), onPressed: () { setState(() { ++count; }); }) ], ), ), ); } }
大家注意到,demo中操作++count
时,使用了setState
手动触发控件进行刷新。
结论
InheritedWidget
只提供我们共享数据的能力,以及控制是否在 build 前触发didChangeDependencies
的能力。不会主动触发build
方法,如果build
没被触发,那么didChangeDependencies
也不会被触发。
号外扩展
InheritedWidget 数据共享能力不会受到 Navigator push
新页面的影响,与原生不一样,flutter的页面跳转不是管理一个堆栈,Navigator
本质上是使用 overlay
管理一个 stack
widget,因此 InheritedWidget
基于父子关系管理的数据共享条件没有被打破
以上就是flutter InheritedWidget使用方法总结的详细内容,更多关于flutter InheritedWidget使用的资料请关注好代码网其它相关文章!