共享状态管理(InheritedWidget)简单使用

共享状态管理-InheritedWidget的简单使用

InheritedWidget是 Flutter 中非常重要的一个功能型组件,它提供了一种在 widget 树中从上到下共享数据的方式,

InheritedWidget和React中的context功能类似,可以实现跨组件数据的传递。InheritedWidget的在 widget 树中数据传递方向是从上到下的。

先查看InheritedWidget 源码,

  • InheritedWidget 的构造中需要传入 child,这个child就是需要使用共享数据的子widget
  • updateShouldNotify 这个抽象方法需要子类实现
abstract class InheritedWidget extends ProxyWidget {
    
    
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const InheritedWidget({
    
     super.key, required super.child });

  
  InheritedElement createElement() => InheritedElement(this);

  /// Whether the framework should notify widgets that inherit from this widget.
  ///
  /// When this widget is rebuilt, sometimes we need to rebuild the widgets that
  /// inherit from this widget but sometimes we do not. For example, if the data
  /// held by this widget is the same as the data held by `oldWidget`, then we
  /// do not need to rebuild the widgets that inherited the data held by
  /// `oldWidget`.
  ///
  /// The framework distinguishes these cases by calling this function with the
  /// widget that previously occupied this location in the tree as an argument.
  /// The given widget is guaranteed to have the same [runtimeType] as this
  /// object.
  
  bool updateShouldNotify(covariant InheritedWidget oldWidget);
}

来定义 “计数器”示例应用程序一个共享数据的InheritedWidget,需要继承自 InheritedWidget, 如下:

class CounterWidget extends InheritedWidget {
    
    
  // 1.需要共享的数据
  final int counter;

  // 2.定义构造方法 传入最新的 counter值
  CounterWidget({
    
    this.counter, Widget child}): super(child: child);

  // 3.获取组件最近的当前InheritedWidget
  static CounterWidget of(BuildContext context) {
    
    
    // 沿着Element树, 去找到最近的CounterElement, 从Element中取出Widget对象
    return context.dependOnInheritedWidgetOfExactType();
  }

  // 4.绝对要不要回调State中的didChangeDependencies
  // 如果返回true: 执行依赖当期的InheritedWidget的State中的 didChangeDependencies
  
  bool updateShouldNotify(CounterWidget oldWidget) {
    
    
    return oldWidget.counter != counter;
  }
}
  • 需要共享的数据 为 int 类型的 counter

  • 在构造中给counter 赋值,child 是需要使用数据的widget

  • 定义了一个of方法,该方法通过context开始去查找祖先的 CounterWidget

  • updateShouldNotify方法是对比新旧CounterWidget,是否需要对更新相关依赖的Widget

    如果返回true: 执行依赖当期的InheritedWidget的State中的 didChangeDependencies

在示例中去使用CounterWidget, 定义 ShowDataWidget 子组件使用共享的数据:

class _HomePageState extends State<HomePage> {
    
    
  int _counter = 100;

  
  Widget build(BuildContext context) {
    
    
    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedWidget"),
      ),
      body: CounterWidget(//使用CounterWidget 将需要使用数据widget包裹
        counter: _counter,
        child: Center(
          child:  ShowDataWidget(),//在ShowDataWidget 中去使用共享的数据
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
    
    
          setState(() {
    
    
            _counter++; 
          });
        },
      ),
    );
  }
}



class ShowDataWidget extends StatefulWidget {
    
    
  
  _ShowDataWidgetState createState() => _ShowDataWidgetState();
}

class _ShowDataWidgetState extends State<ShowDataWidget> {
    
    

  
  void didChangeDependencies() {
    
    
    super.didChangeDependencies();
    print("执行了ShowDataWidget中的didChangeDependencies");
  }

  
  Widget build(BuildContext context) {
    
    
    int counter = CounterWidget.of(context).counter;

    return Card(
      color: Colors.red,
      child: Text("当前计数: $counter", style: TextStyle(fontSize: 30),),CounterWidget
    );
  }
}

我们可以看到:

  • 这里 按下floatingActionButton 之后 ,调用setState 重新调用_HomePageState的 build 方法,然后重新创建CounterWidget 传入最新的counter 值。

  • ShowDataWidget中 通过调用CounterWidget中的 **of **方法 获取CounterWidget 实例,得到共享数据counter

     int counter = CounterWidget.of(context).counter;
    
  • 我们看到_ShowDataWidgetState 中的 didChangeDependencies方法被调用

    关于 didChangeDependencies方法 会在“依赖”发生变化时被Flutter 框架调用。而这个“依赖”指的就是子 widget 是否使用了父 widget 中InheritedWidget的数据!如果使用了,则代表子 widget 有依赖;如果没有使用则代表没有依赖。这种机制可以使子组件在所依赖的InheritedWidget变化时来更新自身!比如当主题、locale(语言)等发生变化时,依赖其的子 widget 的didChangeDependencies方法将会被调用.

    2022-11-09 13:11:06.175 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies
    2022-11-09 13:11:07.383 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies
    2022-11-09 13:11:08.248 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies
    2022-11-09 13:11:08.999 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies
    

效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/MrLizuo/article/details/127770093