flutter 状态管理ChangeNotifier 源码分析-3

ChangeNotifier 源码
class ChangeNotifier implements Listenable {
  //固定长度通知集合 使用 [VoidCallback] 通知的 API
  static final List<VoidCallback?> _emptyListeners = List<VoidCallback?>.filled(0, null);
  List<VoidCallback?> _listeners = _emptyListeners;
  int _notificationCallStackDepth = 0;
  int _reentrantlyRemovedListeners = 0;
  //监听数量
  int _count = 0;
  @protected
  bool get hasListeners {
    //判断是否还有监听
    return _count > 0;
  }
  //在分析1的时候已经添加
  //如果一个监听器被添加了两次,并且在一次迭代中被移除了一次 它仍然会被再次调用 无法确定是哪个监听器被移除,因为它们是相同的
  //它被删除的次数与注册的次数一样多,然后它将不再被调用
  @override
  void addListener(VoidCallback listener) {
    if (_count == _listeners.length) {
      if (_count == 0) {
        _listeners = List<VoidCallback?>.filled(1, null);
      } else {
        final List<VoidCallback?> newListeners =
        List<VoidCallback?>.filled(_listeners.length * 2, null);
        for (int i = 0; i < _count; i++) {
          newListeners[i] = _listeners[i];
        }
        _listeners = newListeners;
      }
    }
    _listeners[_count++] = listener;
  }

  //出于性能原因,优化侦听器的列表长度
  void _removeAt(int index) {
    _count -= 1;
    if (_count * 2 <= _listeners.length) {
      final List<VoidCallback?> newListeners = List<VoidCallback?>.filled(
          _count, null);

      for (int i = 0; i < index; i++)
        newListeners[i] = _listeners[i];

      for (int i = index; i < _count; i++)
        newListeners[i] = _listeners[i + 1];

      _listeners = newListeners;
    } else {
      for (int i = index; i < _count; i++)
        _listeners[i] = _listeners[i + 1];
      _listeners[_count] = null;
    }
  }

  //移除监听
  @override
  void removeListener(VoidCallback listener) {
    for (int i = 0; i < _count; i++) {
      final VoidCallback? listenerAtIndex = _listeners[i];
      if (listenerAtIndex == listener) {
        if (_notificationCallStackDepth > 0) {
          _listeners[i] = null;
          _reentrantlyRemovedListeners++;
        } else {
          _removeAt(i);
        }
        break;
      }
    }
  }

//开始通知 可能多个地方调
    void notifyListeners() {
      if (_count == 0)
        return;

      _notificationCallStackDepth++;

      final int end = _count;
      for (int i = 0; i < end; i++) {
        try {
//开始回调通知到当前元素从重建
          _listeners[i]?.call();
        }
      }

      _notificationCallStackDepth--;
//开始优化列表长度
      if (_notificationCallStackDepth == 0 && _reentrantlyRemovedListeners > 0) {
        final int newLength = _count - _reentrantlyRemovedListeners;
        if (newLength * 2 <= _listeners.length) {
          final List<VoidCallback?> newListeners = List<VoidCallback?>.filled(newLength, null);
          int newIndex = 0;
          for (int i = 0; i < _count; i++) {
            final VoidCallback? listener = _listeners[i];
            if (listener != null) {
              newListeners[newIndex++] = listener;
            }
          }
          _listeners = newListeners;
        } else {
          for (int i = 0; i < newLength; i += 1) {
            if (_listeners[i] == null) {
              // We swap this item with the next not null item.
              int swapIndex = i + 1;
              while(_listeners[swapIndex] == null) {
                swapIndex += 1;
              }
              _listeners[i] = _listeners[swapIndex];
              _listeners[swapIndex] = null;
            }
          }
        }

        _reentrantlyRemovedListeners = 0;
        _count = newLength;
      }
    }
  }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值