Shared state management (InheritedWidget) is easy to use

Shared state management - simple use of InheritedWidget

InheritedWidgetIt is a very important functional component in Flutter, which provides a way to share data from top to bottom in the widget tree,

InheritedWidgeThe functions in t and Reactin contextare similar, and can realize the transfer of cross-component data. InheritedWidgetThe direction of data transfer in the widget tree is from top to bottom.

First look at InheritedWidgetthe source code,

  • In the construction of InheritedWidget, a child needs to be passed in, and this child is a sub-widget that needs to use shared data
  • updateShouldNotify This abstract method needs to be implemented by subclasses
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);
}

To define a shared data for the "counter" sample application InheritedWidget, it needs to inherit from InheritedWidget, as follows:

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;
  }
}
  • The data to be shared is a counter of type int

  • Assign a value to the counter in the construction, and the child is the widget that needs to use the data

  • Defines an of method, which starts to find the ancestors through the contextCounterWidget

  • updateShouldNotifyThe method is to compare the old and new CounterWidget, and whether to update the Widget that depends on it

    If it returns true: Execution depends on the state of the current InheritedWidgetdidChangeDependencies

To use in the example CounterWidget, define the ShowDataWidget subcomponent to use shared data:

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
    );
  }
}

We can see that:

  • After pressing the floatingActionButton here, call setState to re-call the build method of _HomePageState, and then re-create and CounterWidgetpass in the latest counter value.

  • ShowDataWidgetGet the instance by calling CounterWidgetthe **of** method in , CounterWidgetand get the shared data counter

     int counter = CounterWidget.of(context).counter;
    
  • We see that the method _ShowDataWidgetStatein didChangeDependenciesis called

    The method will be called didChangeDependenciesby the Flutter framework when the "dependency" changes. And this "dependency" refers to whether the child widget uses the data of the InheritedWidget in the parent widget! If it is used, it means that the sub-widget has dependencies; if it is not used, it means it has no dependencies. This mechanism allows subcomponents to update themselves when the dependent InheritedWidget changes! For example, when the theme, locale (language), etc. change, the didChangeDependencies method of the sub-widget that depends on it will be called.

    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
    

The effect is as follows:
insert image description here

Guess you like

Origin blog.csdn.net/MrLizuo/article/details/127770093