Flutter InheritedWidget的使用

149 阅读2分钟

Flutter InheritedWidget的使用

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

// 全局状态管理
// 继承InheritedWidget
// 实现抽象方法 updateShouldNotify
// 定义共享状态
class CounterWidget extends InheritedWidget{
  //1.共享数据
  final int counter;
  //2.定义构造方法
  CounterWidget({this.counter , Widget child}): super(child:child);  // 将子类的widget 传给InheritedWidget的父类
  //3.获取组件最近的当前InheritedWidget
  static CounterWidget of (BuildContext context){
    // 沿着Element树,去找到最近的CounterWidget,从Element中取出Widget对象
    return context.dependOnInheritedWidgetOfExactType();
  }
  //4.绝对需不需要回调State中的didChangeDependencies的方法
  @override
  // 如果返回true 执行依赖当前的InheritedWidget的State中的didChangeDependencies
  bool updateShouldNotify(CounterWidget oldWidget) {
    // TODO: implement updateShouldNotify  更新时需不需要通知
    return oldWidget.counter != counter;
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HYStateContent(),
    );
  }
}

class HYStateContent extends StatefulWidget {
  @override
  _HYStateContentState createState() => _HYStateContentState();
}

class _HYStateContentState extends State<HYStateContent> {
  int _counter = 100;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedWidget"),
      ),
      body: CounterWidget(  //使用全局共享属性 需要包裹上这个CounterWidget才能共享在状态
        counter: _counter,
        child: Center(
          child: Column(er
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              HYContent01(),
              HYContent02()
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed:(){
          setState(() {
            _counter++;
          });
        },
      ),
    );
  }
}

class HYContent01 extends StatefulWidget {

  @override
  _HYContent01State createState() => _HYContent01State();
}

class _HYContent01State extends State<HYContent01> {
  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();  
    print("执行了_HYContent01State的didChangeDependencies的生命周期函数");
  }

  @override
  Widget build(BuildContext context) {
    int counter = CounterWidget.of(context).counter;
    return Card(
      color: Colors.pinkAccent,
      child: Text("$counter",style: TextStyle(fontSize: 30)),
    );
  }
}

class HYContent02 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    int counter = CounterWidget.of(context).counter;
    return Container(
      color: Colors.blue,
      child: Text('$counter',style: TextStyle(fontSize: 30),),
    );
  }
}

CounterWidget当中将updateShouldNotify的返回值

  • true 表示执行依赖当前的InheritedWidget的State中的didChangeDependencies
  • fasle 不执行依赖当前的InheritedWidget的State中的didChangeDependencies

改成true,点击添加按钮时,就会执行此didChangeDependencies生命周期函数

数据是如何传递的

dependOnInheritedWidgetOfExactType 是一个抽象方法,子类肯定是有实现的 Ctrl + Alt + B 可以查看

继续往下查找 _inheritedWidget

_inheritedWidget 是一个Map,映射

final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[T];

先判断_inheritedWidgets是否为空,如果为空,直接返回空,不为空的话从_inheritedWidgets[] 当中放入一个T 这个个T 相当于我们当前的 CounterWidget

然后赋值给 ancestor 判断是否为空,不为空的话调用 dependOnInheritedElement(ancestor, aspect: aspect) as T;

这个 _dependencies 目的是在进行数据刷新的时候要不要执行 didChangeDependencies 这个方法

最后返回了 return ancestor.widget

这个地方我们本质上是拿到的是 Element 然后Element.widget,把Widget对象取出将他返回给 CounterWidgetCounterWidget 有counter,就可以将counter共享了