Flutter InheritedWidget 详解

InheritedWidget简介

用于在 widget 树中高效地向下传递数据,允许子组件获取最近Widget树中的InheritedWidget的数据

  1. 数据共享:在 widget 树中向下共享数据
  2. 高效更新:当数据变化时,只重建依赖该数据的子 widget
  3. 自动依赖管理:子 widget 自动"注册"为依赖项(dependOn)

示例

组件结构

子组件TextShowWidget 通过dependOnInheritedWidgetOfExactType()NameInheritedWidget关联,当InputNameWidget组件TextFiled输入变化的时,触发NameInheritedWidget变化,当updateShouldNotify返回true,从而通知和NameInheritedWidget关联的组件TextShowWidget变化

代码示例

TestInheritedWidget/AppChildInheritedWidget

在Flutter中Widget是不可变的,InheritedWidget也是一个Widget,所有要更新widget还是得构造一个StatfulWidget,通过setState()来更新, 在 AppChildInheritedWidget中当name发生变化,重新rebuild,来更新NameInheritedWidget数据, 但是此时的InputShowWidget是通过构造方法传入的,不会改变

scala 复制代码
class TestInheritedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("TestInheritedWidget111");
    return Scaffold(
        appBar: AppBar(
          title: Text(
            "Inherited",
            style: TextStyle(fontSize: 28, color: Colors.white),
          ),
          backgroundColor: Color(0xFFE51BE5),
        ),
        body: AppChildInheritedWidget(child: InputShowWidget()));
  }
}

class AppChildInheritedWidget extends StatefulWidget {
  final Widget child;

  const AppChildInheritedWidget({required this.child, super.key});

  @override
  State<AppChildInheritedWidget> createState() => _AppChildInheritedWidgetState();
}

class _AppChildInheritedWidgetState extends State<AppChildInheritedWidget> {
  String? name;

  @override
  Widget build(BuildContext context) {
    return NameInheritedWidget(
      child: widget.child,
      name: name,
      onNameChange: (value) {
        setState(() {
          name = value;
        });
      },
    );
  }
}

NameInheritedWidget

dependOnInheritedWidgetOfExactType和 InheritedWidget 产生依赖关系,主动获取数据,当InheritedWidget数据变化时,关联的组件也会自动更新(build),

getInheritedWidgetOfExactType 单纯的获取InheritedWidget的数据,不产生关联,被动获取,

updateShouldNotify比较新旧widget数据是否一致,true触发更新

typescript 复制代码
class NameInheritedWidget extends InheritedWidget {
  final String? name;
  void Function(String? name) onNameChange;
  NameInheritedWidget({required super.child, this.name, required this.onNameChange});

  static String? of(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<NameInheritedWidget>()!
        .name;
  }
  
  static String? maybe(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<NameInheritedWidget>()
        ?.name;
  }

  static NameInheritedWidget? getNameInheritedWidget(BuildContext context) {
    return context.getInheritedWidgetOfExactType<NameInheritedWidget>();
  }

  @override
  bool updateShouldNotify(covariant NameInheritedWidget oldWidget) {
    return oldWidget.name != this.name;
  }
}

InputShowWidget

scala 复制代码
class InputShowWidget extends StatelessWidget {
  const InputShowWidget({super.key});

  @override
  Widget build(BuildContext context) {
    print("InputShowWidget222");
    return Column(
      children: [
        Expanded(flex: 2, child: InputNameWidget()),
        Expanded(flex: 1, child: TextShowWidget())
      ],
    );
  }
}

class TextShowWidget extends StatelessWidget {
  const TextShowWidget({super.key});

  @override
  Widget build(BuildContext context) {
    print("TextShowWidget");
    var name = NameInheritedWidget.maybe(context) ?? "未知输入";
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Center(
          child: Text(
        name,
        style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.w600,
            color: Colors.deepOrangeAccent),
      )),
    );
  }
}

InputNameWidget/TextShowWidget

less 复制代码
class InputNameWidget extends StatefulWidget {
  const InputNameWidget({super.key});

  @override
  State<InputNameWidget> createState() => _InputNameWidgetState();
}

class _InputNameWidgetState extends State<InputNameWidget> {
  TextEditingController _textEditingController = TextEditingController(text: "爱好");
  
  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
    _textEditingController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print("InputNameWidget333");
    return LayoutBuilder(builder: (context, constraints) {
      return SingleChildScrollView(
        child: ConstrainedBox(
          constraints: BoxConstraints(minHeight: constraints.maxHeight),
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: Column(
              spacing: 20,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextField(
                  style: TextStyle(color: Colors.pink),
                  controller: _textEditingController,
                  onChanged: (value){
                    print(value);
                    NameInheritedWidget.getNameInheritedWidget(context)
                        ?.onNameChange(value);
                  },
                  decoration: InputDecoration(
                      focusColor: Colors.red,
                      hintText: "请输入",
                      hintStyle: TextStyle(color: Colors.blueAccent),
                      border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(12),
                          borderSide: BorderSide.none),
                      focusedBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(12),
                          borderSide: BorderSide(color: Colors.black)),
                      filled: true,
                      fillColor: Color(0xE5BBBBC4)),
                ),
                SizedBox(height: 20,),
                FilledButton(
                    style: ButtonStyle(
                        backgroundColor: WidgetStatePropertyAll(Colors.black),
                        padding: WidgetStatePropertyAll(
                            EdgeInsets.symmetric(vertical: 18)),
                        shape: WidgetStatePropertyAll(RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(12)))),
                    onPressed: () {
                      NameInheritedWidget.getNameInheritedWidget(context)
                          ?.onNameChange(_textEditingController.text);
                    },
                    child: Text("点击"))
              ],
            ),
          ),
        ),
      );
    });
  }
}
scala 复制代码
class TextShowWidget extends StatelessWidget {
  const TextShowWidget({super.key});

  @override
  Widget build(BuildContext context) {
    print("TextShowWidget");
    var name = NameInheritedWidget.maybe(context) ?? "未知输入";
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Center(
          child: Text(
        name,
        style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.w600,
            color: Colors.deepOrangeAccent),
      )),
    );
  }
}

日志

首次进入所有Widget的build方法全部执行

TextField发生变化,触发底部文字变化

dependOnInheritedWidgetOfExactType探索如何关联

相关推荐
亚历克斯神5 小时前
Flutter for OpenHarmony: Flutter 三方库 mutex 为鸿蒙异步任务提供可靠的临界资源互斥锁(并发安全基石)
android·数据库·安全·flutter·华为·harmonyos
钛态5 小时前
Flutter 三方库 smartstruct 鸿蒙化字段映射适配指南:介入静态预编译引擎扫除视图及数据模型双向强转类型错乱隐患,筑稳如磐石的企业级模型治理防线-适配鸿蒙 HarmonyOS ohos
flutter·华为·harmonyos
键盘鼓手苏苏5 小时前
Flutter 组件 csv2json 适配鸿蒙 HarmonyOS 实战:高性能异构数据转换,构建 CSV 流式解析与全栈式数据映射架构
flutter·harmonyos·鸿蒙·openharmony
左手厨刀右手茼蒿5 小时前
Flutter 组件 http_requests 适配鸿蒙 HarmonyOS 实战:极简网络请求,构建边缘端轻量级 RESTful 通讯架构
网络·flutter·http
雷帝木木5 小时前
Flutter 三方库 hrk_logging 的鸿蒙化适配指南 - 实现标准化分层日志记录、支持多目的地输出与日志分级过滤
flutter·harmonyos·鸿蒙·openharmony·hrk_logging
左手厨刀右手茼蒿5 小时前
Flutter 三方库 dio_compatibility_layer 的鸿蒙化适配指南 - 实现 Dio 跨主版本的平滑迁移、支持遗留拦截器兼容与网络请求架构稳定升级
flutter·harmonyos·鸿蒙·openharmony·dio_compatibility_layer
雷帝木木5 小时前
Flutter 三方库 hashids2 基于鸿蒙安全内核的深度隐匿映射适配:数字指纹泄露防御层、生成短小精悍唯一不可逆加盐哈希,护航全链路请求 URL 隐私-适配鸿蒙 HarmonyOS ohos
安全·flutter·harmonyos
王码码20358 小时前
Flutter 组件 inappwebview_cookie_manager 适配 鸿蒙Harmony 实战 - 驾驭核心大 Web 容器缓存隧道、构建金融级政企应用绝对防串号跨域大隔离基座
flutter·harmonyos·鸿蒙·openharmony·inappwebview_cookie_manager
左手厨刀右手茼蒿8 小时前
Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 驾驭企业级 Exchange Web Services 协议、实现鸿蒙端政企办公同步与高安通讯隔离方案
flutter·harmonyos·鸿蒙·openharmony
钛态8 小时前
Flutter 三方库 react 泛前端核心范式框架鸿蒙原生层生态级双向超能适配:跨时空重塑响应式单向数据流拓扑与高度精密生命周期树引擎解耦视图渲染控制中枢(适配鸿蒙 HarmonyOS ohos)
前端·flutter·react.js