当前位置:网站首页>从源码解析 MobX 响应式刷新机制
从源码解析 MobX 响应式刷新机制
2022-06-12 18:16:00 【InfoQ】
前言
Observer 类

StatelessObserverWidget
abstract class StatelessObserverWidget extends StatelessWidget
with ObserverWidgetMixin {
/// Initializes [key], [context] and [name] for subclasses.
const StatelessObserverWidget(
{Key? key, ReactiveContext? context, String? name})
: _name = name,
_context = context,
super(key: key);
final String? _name;
final ReactiveContext? _context;
@override
String getName() => _name ?? '$this';
@override
ReactiveContext getContext() => _context ?? super.getContext();
@override
StatelessObserverElement createElement() => StatelessObserverElement(this);
}
createElementStatelessWidgetStatelessObserverElementElementObserverWidgetMixin
WidgetmixincreateReactionreactioncreateReactionObserverElementMixinmixin ObserverWidgetMixin on Widget {
String getName();
ReactiveContext getContext() => mainContext;
@visibleForTesting
Reaction createReaction(
Function() onInvalidate, {
Function(Object, Reaction)? onError,
}) =>
ReactionImpl(
getContext(),
onInvalidate,
name: getName(),
onError: onError,
);
void log(String msg) {
debugPrint(msg);
}
}
StatelessObserverElement
StatelessObserverElementStatelessElementObserverElementMixinObserverElementMixinObserverElementMixinmixin 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();
@override
Widget build() {
late Widget built;
reaction.track(() {
built = super.build();
});
if (!reaction.hasObservables) {
_widget.log(
'No observables detected in the build method of ${reaction.name}',
);
}
return built;
}
@override
void unmount() {
reaction.dispose();
super.unmount();
}
}
mixinElemenntmountmountreactioninvalidateinvalidatemarkNeedsBuildreactionmarkNeedsBuildElementWidgetbuildmixinbuildreactiontrackobserverObserverbuilderwidgetvoid _bindDependencies(Derivation derivation) {
final staleObservables =
derivation._observables.difference(derivation._newObservables!);
final newObservables =
derivation._newObservables!.difference(derivation._observables);
var lowestNewDerivationState = DerivationState.upToDate;
// Add newly found observables
for (final observable in newObservables) {
observable._addObserver(derivation);
// Computed = Observable + Derivation
if (observable is Computed) {
if (observable._dependenciesState.index >
lowestNewDerivationState.index) {
lowestNewDerivationState = observable._dependenciesState;
}
}
}
// Remove previous observables
for (final ob in staleObservables) {
ob._removeObserver(derivation);
}
if (lowestNewDerivationState != DerivationState.upToDate) {
derivation
.._dependenciesState = lowestNewDerivationState
.._onBecomeStale();
}
derivation
.._observables = derivation._newObservables!
.._newObservables = {}; // No need for newObservables beyond this point
}
状态对象跟踪
@observablefinal _$praiseCountAtom = Atom(name: 'ShareStoreBase.praiseCount');
@override
int get praiseCount {
_$praiseCountAtom.reportRead();
return super.praiseCount;
}
@override
set praiseCount(int value) {
_$praiseCountAtom.reportWrite(value, super.praiseCount, () {
super.praiseCount = value;
});
}
getAtomreportRead_reportObservedObservervoid _reportObserved(Atom atom) {
final derivation = _state.trackingDerivation;
if (derivation != null) {
derivation._newObservables!.add(atom);
if (!atom._isBeingObserved) {
atom
.._isBeingObserved = true
.._notifyOnBecomeObserved();
}
}
}
setsetAtomreportWritereaction void schedule() {
if (_isScheduled) {
return;
}
_isScheduled = true;
_context
..addPendingReaction(this)
..runReactions();
}
reaction_run_onInvalidateObserverElementMixincreateReactionWidgetbuildvoid _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();
}
总结
- 控制渲染的
Element是StatelessObserverElement,该类在mount阶段通过createReaction注册了reaction。
StatelessObserverElement在build方法中reaction和observable进行绑定。
- 在
Observer中读取状态对象属性时,会调用到其get方法,该方法会将状态对象属性与对应的Observer组件 进行绑定。
- 当状态对象的属性被
set更改的时候,会调度到该属性绑定的reaction,执行_onInvalidate方法来进行刷新,从而实现了响应式的无感知刷新。

边栏推荐
- MYSQL:Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column
- Typescript advanced type (2)
- Window版本pytorch入门深度学习环境安装与配置
- torch.where的新用法(很老但是大家忽略的用法)
- 机器学习系列(3):Logistic回归
- Pytest automated testing framework (II)
- String s = null ; String s = new String(); String s = "; what is the difference between string s?
- MYSQL:Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column
- 01 complexity
- 1.5 what is an architect (serialization)
猜你喜欢

USB to serial port - maximum peak serial port baud rate vs maximum continuous communication baud rate

Global lock, table lock, row lock

High-Speed Layout Guidelines 未完...

Esp-idf adds its own components

轻量、便捷的小程序转App技术方案,实现与微信/流量App互联互通

Vant3 +ts packaged simple step advancer component

有源差分晶振原理图以及LV-PECL、LVDS、HCSL区别

GD32F4xx控制DGUS 变量显示

Introduction to service grid and istio - continued

Make good use of IDE, speed up R & D efficiency by 100%
随机推荐
Introduction to reinforcement learning and analysis of classic items 1.3
有源差分晶振原理圖以及LV-PECL、LVDS、HCSL區別
Random talk about redis source code 91
JS judge palindromes
High-Speed Layout Guidelines 未完...
PHP:Fatal error: Allowed memory size of 262144 bytes exhausted (tried to allocat
VirtualLab基礎實驗教程-4.單縫衍射
JS for Fibonacci sequence
MYSQL:Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column
C语言练习(4)——大数乘除
PHP:Fatal error: Allowed memory size of 262144 bytes exhausted (tried to allocat
小程序+App,低成本获客及活跃的一种技术组合思路
Applet and app are owned at the same time? A technical scheme with both
Machine learning series (3): logistic regression
面试题总结
01-复杂度
Vant3+ts encapsulates uploader upload image component
USB to serial port - serial port driver type
Schedule update | 2022 Microsoft and Intel hacker song competition is in hot registration
Changes in the third generation dri