Flutter中Mobx的实现原理

Mobx 可能先前H5 使用的较多,楼主为Android 原生开发转Flutter ,对Mobx较为陌生,在使用Mobx时想确认该框架如何实现局部刷新。

本文只涉及Mobx 局部刷新的实现原理,Mobx的具体使用方法,可以百度查询

Mobx会自动创建xxxx.g.dart 文件

  @override
  String? get currentShowCard {
    _$currentShowCardAtom.reportRead();
    return super.currentShowCard;
  }

  @override
  set currentShowCard(String? value) {
    _$currentShowCardAtom.reportWrite(value, super.currentShowCard, () {
      super.currentShowCard = value;
    });
  }

可以看到,set方法调用时会使用到reporWrite方法

  void reportWrite<T>(T newValue, T oldValue, void Function() setNewValue) {
    context.spyReport(ObservableValueSpyEvent(this,
        newValue: newValue, oldValue: oldValue, name: name));

    final actionName = context.isSpyEnabled ? '${name}_set' : name;

    // ignore: cascade_invocations
    context.conditionallyRunInAction(() {
      setNewValue();
      reportChanged();
    }, this, name: actionName);

    // ignore: cascade_invocations
    context.spyReport(EndedSpyEvent(type: 'observable', name: name));
  }
    context.conditionallyRunInAction(() {
      setNewValue();
      reportChanged();
    }, this, name: actionName);

这里reportChanged()就是通知刷新的入口。

  void reportChanged() {
    _context
      ..startBatch()
      ..propagateChanged(this)
      ..endBatch();
  }
..propagateChanged(this)是重点
  void propagateChanged(Atom atom) {
    if (atom._lowestObserverState == DerivationState.stale) {
      return;
    }

    atom._lowestObserverState = DerivationState.stale;

    for (final observer in atom._observers) {
      if (observer._dependenciesState == DerivationState.upToDate) {
        observer._onBecomeStale();
      }
      observer._dependenciesState = DerivationState.stale;
    }
  }

可以看到这个方法里面有个循环,轮询通知各个监听刷新状态,oberver是Derivation 抽象类的实现

abstract class Derivation {
  String get name;
  late Set<Atom> _observables;
  Set<Atom>? _newObservables;

  MobXCaughtException? _errorValue;
  MobXCaughtException? get errorValue;

  late DerivationState _dependenciesState;

  void _onBecomeStale();

  // ignore: unused_element
  void _suspend();
}

我们接着跟踪源码

abstract class Reaction implements Derivation {
  bool get isDisposed;

  void dispose();

  void _run();
}

class ReactionImpl implements Reaction {
  ReactionImpl(this._context, Function() onInvalidate,
      {required this.name, void Function(Object, Reaction)? onError}) {
    _onInvalidate = onInvalidate;
    _onError = onError;
  }
...
}

可以看到ReactionImpl是具体实现类,那么具体刷新逻辑肯定也就是由它实现的

  @override
  void _onBecomeStale() {
    schedule();
  }

ReactionImpl 的 _onBecomeStale 方法很简明,继续往下看

  void schedule() {
    if (_isScheduled) {
      return;
    }

    _isScheduled = true;
    _context
      ..addPendingReaction(this)
      ..runReactions();
  }
..runReactions() 重点在方法
  void runReactions() {
    if (_state.batch > 0 || _state.isRunningReactions) {
      return;
    }

    _runReactionsInternal();
  }

  void _runReactionsInternal() {
    _state.isRunningReactions = true;

    ...

      final remainingReactions = allReactions.toList(growable: false);
      allReactions.clear();
      for (final reaction in remainingReactions) {
        reaction._run();
      }
    }

    _state
      ..pendingReactions = []
      ..isRunningReactions = false;
  }
_runReactionsInternal 方法里面有个轮询调用reaction._run();
ReactionImpl 类里面有_run() 方法具体实现逻辑。
  @override
  void _run() {
    if (_isDisposed) {
      return;
    }

    _context.startBatch();

    _isScheduled = false;

    if (_context._shouldCompute(this)) {
      try {
        _onInvalidate();
      } on Object catch (e, s) {
        // Note: "on Object" accounts for both Error and Exception
        _errorValue = MobXCaughtException(e, stackTrace: s);
        _reportException(_errorValue!);
      }
    }

    _context.endBatch();
  }

_onInvalidate() 方法就是最终的实现方法。该方法是在ReactionImpl构造方法传入

  ReactionImpl(this._context, Function() onInvalidate,
      {required this.name, void Function(Object, Reaction)? onError}) {
    _onInvalidate = onInvalidate;
    _onError = onError;
  }
mixin ObserverWidgetMixin on Widget {
  /// An identifiable name that can be overriden for debugging.
  String getName();

  /// The context within which its reaction should be run. It is the
  /// [mainContext] in most cases.
  ReactiveContext getContext() => mainContext;

  /// A convenience method used for testing.
  @visibleForTesting
  Reaction createReaction(
    Function() onInvalidate, {
    Function(Object, Reaction)? onError,
  }) =>
      ReactionImpl(
        getContext(),
        onInvalidate,
        name: getName(),
        onError: onError,
      );
 ...
}
mixin ObserverElementMixin on ComponentElement {
  ReactionImpl get reaction => _reaction;
  late ReactionImpl _reaction;

  // Not using the original `widget` getter as it would otherwise make the mixin
  // impossible to use
  ObserverWidgetMixin get _widget => widget as ObserverWidgetMixin;

  @override
  void mount(Element? parent, dynamic newSlot) {
    _reaction = _widget.createReaction(invalidate, onError: (e, _) {
      FlutterError.reportError(FlutterErrorDetails(
        library: 'flutter_mobx',
        exception: e,
        stack: e is Error ? e.stackTrace : null,
      ));
    }) as ReactionImpl;
    super.mount(parent, newSlot);
  }

  void invalidate() => markNeedsBuild();
 ...
}

最后我们终于找到了最终节点invalidate() 方法

总上,Mobx 在变量更新后调用markNeedsBuild() 来通知Flutter 框架进行更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值