setState局部刷新与InheritedWidget源码【flutter性能优化指南以及源码分析】

setState与局部刷新

setState想必对大家都很熟悉,你可以使用setState来刷新页面数据。setState源码如下:

@protected
void setState(VoidCallback fn) {
    ...
    _element!.markNeedsBuild();
}

setState确实是一个大家耳熟能详的刷新页面的方法,但是setState有一个不好的地方,也就是它会将整个widget全部刷新。但是有时候我们只是更改页面中某个角落里的小数据,完全不需要全局刷新。因此,局部刷新对我们来说是一个非常好的解决办法。

InheritedWidget源码

在说我们的主角Provider之前,我们先来说说InheritedWidget。

InheritedWidget是一种从上到下数据共享的方式,你在根Widget上共享了一个数据,那个你在任意子Widget上都可以是使用这个数据。首先我们还是从源码进行分析:

abstract class InheritedWidget extends ProxyWidget {
  /// 抽象的构造函数。这个构造函数使子类能够提供构造函数,从而使它们能够在构造表达式中使用。
  const InheritedWidget({ Key? key, required Widget child })
    : super(key: key, child: child);

  @override
  InheritedElement createElement() => InheritedElement(this);

  /// 框架是否应该通知继承自这个小组件的组件。
  /// 当这个小组件被重建时,有时我们需要重建继承自这个小组件的组件,但有时我们不需要。例如,如果这个小组件持有的数据与
  /// oldWidget持有的数据相同,那么我们不需要重建继承了oldWidget持有的数据的小组件。
  /// 框架通过调用这个函数来区分这些情况,并将之前在树中占据这个位置的widget作为一个参数。给定的widget被保证具有与此对象相同的
  /// 运行时类型。
  @protected
  bool updateShouldNotify(covariant InheritedWidget oldWidget);
}
class InheritedElement extends ProxyElement {
  /// 使用给定的部件作为其配置创建一个元素。
  InheritedElement(InheritedWidget widget) : super(widget);
   
  // get方法实现
  @override
  InheritedWidget get widget => super.widget as InheritedWidget;

  final Map<Element, Object?> _dependents = HashMap<Element, Object?>();

  @override
  void _updateInheritance() {
    // 检测生命周期
    assert(_lifecycleState == _ElementLifecycle.active);
    // 获取继承子组件
    final Map<Type, InheritedElement>? incomingWidgets = _parent?._inheritedWidgets;
    if (incomingWidgets != null)
      _inheritedWidgets = HashMap<Type, InheritedElement>.of(incomingWidgets);
    else
      _inheritedWidgets = HashMap<Type, InheritedElement>();
    _inheritedWidgets![widget.runtimeType] = this;
  }

  @override
  void debugDeactivated() {
    assert(() {
      assert(_dependents.isEmpty);
      return true;
    }());
    super.debugDeactivated();
  }

  
  @protected
  Object? getDependencies(Element dependent) {
    return _dependents[dependent];
  }

  @protected
  void setDependencies(Element dependent, Object? value) {
    _dependents[dependent] = value;
  }

  
  @protected
  void updateDependencies(Element dependent, Object? aspect) {
    setDependencies(dependent, null);
  }

  @protected
  void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
    dependent.didChangeDependencies();
  }

  @override
  void updated(InheritedWidget oldWidget) {
    if (widget.updateShouldNotify(oldWidget))
      super.updated(oldWidget);
  }

  @override
  void notifyClients(InheritedWidget oldWidget) {
    assert(_debugCheckOwnerBuildTargetExists('notifyClients'));
    for (final Element dependent in _dependents.keys) {
      assert(() {
        // 检查它是否真的是我们的后代
        Element? ancestor = dependent._parent;
        while (ancestor != this && ancestor != null)
          ancestor = ancestor._parent;
        return ancestor == this;
      }());
      // 检查一下,这真的依赖于我们
      assert(dependent._dependencies!.contains(this));
      // 通知依赖进行更新
      notifyDependent(oldWidget, dependent);
    }
  }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值