You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

InheritedWidget的updateShouldNotify是否必要?求子widget不重建示例

InheritedWidget的updateShouldNotify生效示例

首先要明确:你混淆了InheritedWidget的普通子节点和依赖它的继承widget的区别:

  • InheritedWidget的普通子widget(直接写在它child参数里的组件),确实会随InheritedWidget的重建而重建,因为它们是父子关系。
  • 但那些通过dependOnInheritedWidgetOfExactType(或旧版的inheritFromWidgetOfExactType)获取InheritedWidget数据的widget,属于依赖该InheritedWidget的组件,这类组件是否重建,才由updateShouldNotify的返回值决定。

下面是一个完整的示例,能清晰展示updateShouldNotify的作用:

import 'package:flutter/material.dart';

// 自定义InheritedWidget,持有一个count状态
class CountInherited extends InheritedWidget {
  final int count;
  final VoidCallback onIncrement;

  const CountInherited({
    super.key,
    required this.count,
    required this.onIncrement,
    required super.child,
  });

  // 供子widget获取实例的方法
  static CountInherited? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<CountInherited>();
  }

  @override
  bool updateShouldNotify(covariant CountInherited oldWidget) {
    // 只有当count变化时,才通知依赖的widget
    return oldWidget.count != count;
  }
}

// 依赖CountInherited的组件,会打印重建日志
class CountDisplay extends StatelessWidget {
  const CountDisplay({super.key});

  @override
  Widget build(BuildContext context) {
    print("CountDisplay 重建了");
    final inherited = CountInherited.of(context)!;
    return Text(
      "当前计数: ${inherited.count}",
      style: const TextStyle(fontSize: 20),
    );
  }
}

// 普通子组件,不是通过依赖获取数据,会随InheritedWidget重建
class NormalChild extends StatelessWidget {
  const NormalChild({super.key});

  @override
  Widget build(BuildContext context) {
    print("NormalChild 重建了");
    return const Text("我是普通子组件");
  }
}

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

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int _count = 0;
  int _otherValue = 0; // 这个值变化不会影响CountInherited的updateShouldNotify

  void _incrementCount() {
    setState(() {
      _count++;
    });
  }

  void _changeOtherValue() {
    setState(() {
      _otherValue++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text("updateShouldNotify 示例")),
        body: Center(
          child: CountInherited(
            count: _count,
            onIncrement: _incrementCount,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const CountDisplay(), // 依赖InheritedWidget的组件
                const SizedBox(height: 20),
                const NormalChild(), // 普通子组件
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: _incrementCount,
                  child: const Text("增加计数"),
                ),
                const SizedBox(height: 10),
                ElevatedButton(
                  onPressed: _changeOtherValue,
                  child: const Text("修改无关值"),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

示例运行效果:

  1. 点击修改无关值按钮:

    • 由于_otherValue变化触发setState,CountInherited会重建,但updateShouldNotify对比新旧count值相同,返回false。
    • 控制台会打印NormalChild 重建了(因为它是CountInherited的普通子节点),但不会打印CountDisplay 重建了,说明依赖的组件没有被通知重建。
  2. 点击增加计数按钮:

    • _count变化触发setState,CountInherited重建,updateShouldNotify返回true。
    • 控制台会同时打印NormalChild 重建了和CountDisplay 重建了,说明依赖的组件被通知重建。

这样就能清晰看到updateShouldNotify的作用:它控制的是依赖该InheritedWidget的组件是否收到通知并重建,而非InheritedWidget的所有子节点。

内容的提问来源于stack exchange,提问作者ximmyxiao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:12:13