当前位置:网站首页>从源码解析 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方法来进行刷新,从而实现了响应式的无感知刷新。

边栏推荐
- General differences between SQL server versions released by Microsoft in different periods so far, for reference
- TypeScript高级类型(二)
- MYSQL:Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column
- 低代码平台调研结果
- Remote gadget putty (Alibaba cloud mirror station address sharing)
- 迄今微软不同时期发布的SQL Server各版本之间的大致区别,供参考查阅
- Common dependencies of SSM
- Random talk about redis source code 91
- 一种好用、易上手的小程序IDE
- 网盘和对象云存储管理之磁盘映射工具比较
猜你喜欢

vant3 +ts 封装简易step进步器组件

Machine learning series (3): logistic regression

js两数之和

C#的变量

ES7 does not use parent-child and nested relationships to implement one to many functions

Typescript type declaration file (III)

VirtualLab基础实验教程-4.单缝衍射

Vant3+ts encapsulates uploader upload image component

Solution to the problem that the anaconda navigator card logo cannot be opened and the card will flash back - replace the alicloud image source

Window版本pytorch入门深度学习环境安装与配置
随机推荐
Random talk about redis source code 91
Can tonghuashun open an account? Can tonghuashun directly open the security of securities companies on the app
js判断回文数
小程序和App同时拥有?两者兼得的一种技术方案
JS中的字符串(含leetcode例题)<持续更新~>
USB转串口那些事儿—最大峰值串口波特率VS连续通信最高波特率
LCD parameter interpretation and calculation
VirtualLab basic experiment tutorial -6 Blazed grating
A story on the cloud of the Centennial Olympic Games belonging to Alibaba cloud video cloud
Explanation of core interrupt of Godson processor
leetcode491 递增子序列
用grep awk提取字符串
Schedule update | 2022 Microsoft and Intel hacker song competition is in hot registration
When openharmony meets openeuler
Lightweight and convenient small program to app technology solution to realize interconnection with wechat / traffic app
js两数之和
Pytest automated testing framework (II)
Typescript common types (I)
MYSQL:Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column
JS dichotomy