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

边栏推荐
- 重构--梳理并分解继承体系
- Vant3+ts H5 pages are nested into apps to communicate with native apps
- Still using Microsoft office, 3 fairy software, are you sure you don't want to try?
- LCD parameter interpretation and calculation
- leetcode 674 最长递增子串
- Changes in the third generation dri
- JS中的字符串(含leetcode例题)<持续更新~>
- A method of quickly reusing wechat login authorization in app
- Research results of low code platform
- leetcode 647. Palindrome substring
猜你喜欢

Typescript common types (I)

Installation and configuration of window version pytorch entry depth learning environment

干货 | 一文搞定 pytest 自动化测试框架(二)

Virtual Lab Basic Experiment tutoriel - 4. Diffraction à fente unique

Explanation of core interrupt of Godson processor

GD32F4xx控制DGUS 变量显示

C brief introduction

Write a select based concurrent server

A method of quickly reusing wechat login authorization in app

Vant3+ts dropdownmenu drop-down menu, multi data can be scrolled
随机推荐
关于数据集
An easy-to-use IDE for small programs
PHP:Fatal error: Allowed memory size of 262144 bytes exhausted (tried to allocat
Write a select based concurrent server
js判断回文数
01 complexity
PHP implementation of infinite classification tree (recursion and Optimization)
有源差分晶振原理圖以及LV-PECL、LVDS、HCSL區別
Schematic diagram of active differential crystal oscillator and differences among lv-pecl, LVDS and HCSL
一种好用、易上手的小程序IDE
Leetcode 674 longest incrementing substring
JS中的字符串(含leetcode例题)<持续更新~>
Random talk about redis source code 91
JS for Fibonacci sequence
JS中的数组(含leetcode例题)<持续更新~>
Stack in JS (including leetcode examples) < continuous update ~>
面试题总结
GD32F4xx控制DGUS 变量显示
Leetcode151 flipping words in strings
MYSQL:Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column