AutomaticKeepAliveClientMixin 基本原理

了解了keepalive的大致过程,在项目中,"我的"页内部是一个由tabbar和pageview联动的widget,选中tab时会在widget中保存一个value表示当前位置,但是,如果不做任何处理,当从"我的"切换到其他页面比如"首页"时,"我的"页的widget将会被移出widget tree和销毁,所以重新切回"我的"页时,选中的tab变回默认,但这不是我们想要的表现。flutter提供了一种当widget从tree中remove后仍然保存相关变量的方式——AutomaticKeepAliveClientMixin。

在state后面加上with AutomaticKeepAliveClientMixin,并重写wantKeepAlive的getter,这样任何情况下这个widget都会被保存。

class _MineTabState extends State with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;
}

他的实现原理大致如下,AutomaticKeepAliveClientMixin内部有一个_ensureKeepAlive方法,内部会向上发送一个KeepAliveNotification通知,当initState、updateState以及deactivate时都会发送这个通知:

mixin AutomaticKeepAliveClientMixin on State {
  KeepAliveHandle _keepAliveHandle;

  void _ensureKeepAlive() {
    assert(_keepAliveHandle == null);
    _keepAliveHandle = KeepAliveHandle();
    KeepAliveNotification(_keepAliveHandle).dispatch(context);
  }
}

当上级中有一个widget是AutomaticKeepAlive类型时,内部的NotificationListener会接受这种通知,然后通过childe 的 Element去保存该widget,但是从表现上看,假如AutomaticKeepAlive和发送通知的widget中间隔了几层widget的话,中间的几层widget也会跟着发送通知的widget一起被保存下来。

class _AutomaticKeepAliveState extends State {
  void _updateChild() {
    _child = NotificationListener(
      onNotification: _addClient,
      child: widget.child,
    );
  }

再继续往上查看源码,可以看到,pageview内部是有一个AutomaticKeepAlive类型的widget去包裹child的,这可能就是pageview可以快速支持keepalive的原因了,flutter中似乎所有的可滚动widget都默认开启了keepalive,这应该是滚动的一种优化,减少滚动中item的大量重建。

你可能感兴趣的:(AutomaticKeepAliveClientMixin 基本原理)