Flutter 基于 dart 语言,dart 自己是一个单线程模型,Future 也是基于单线程的异步机制,即基于事件循环实现的异步,与多线程实现的异步并不同,比较相似于 Android 中的 Handler 机制,而所谓的异步,就是向事件循环中心发送一条消息,等待调度,在以后的某个时刻执行代码,可是这段代码仍是在当前线程执行的,因此,若是使用 Future 执行耗时任务,它可能不会阻塞当前的 UI 流程,不事后续的一些 UI 操做仍是会受到影响。 使用 Future 异步执行代码须要四个步骤:markdown
接收到的最终的任务就是一个 callback,参见:多线程
factory Future(FutureOr<T> computation()) {
_Future<T> result = new _Future<T>();
Timer.run(() {
try {
result._complete(computation());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
}
});
return result;
}
复制代码
_complete 函数用于处理 computation 函数执行的结果,分为三种类型判断:app
void _complete(FutureOr<T> value) {
assert(!_isComplete);
if (value is Future<T>) {
if (value is _Future<T>) {
_chainCoreFuture(value, this);
} else {
_chainForeignFuture(value, this);
}
} else {
_FutureListener listeners = _removeListeners();
_setValue(value);
_propagateToListeners(this, listeners);
}
}
复制代码
当返回结果仍是一个 Future 类型时,和当返回结果不是 Future 对象时有这两种不一样的处理逻辑,后者,也就是 else 语句中的逻辑,能够看到就是将返回值传递给 listener ,而后调用 _propagateToListeners 将结果分发给 listener 的 listeners,但前者,if 语句中的逻辑,告诉咱们当上一个 Future 返回出一个 Future 时,不能直接将这个 Future 看成 listener 的 value 而后通知 listener ,这涉及到 Future 使用过程当中的一个规则:Listener 的监听结果不能是一个 Future ,因此就有了以下这种代码:异步
test4() {
print("start");
Future(() {
print("return future");
return Future(() {
print("return test4");
return "test4";
});
}).then((FutureOr<String> s) {
if (s is Future<String>) {
s.then((String ss) {
print(ss + "_");
});
} else {
print(s);
}
});
print("end");
}
复制代码
这段代码最终打印的是 test4 而不是 test4_ ,而这种状况出现的缘由,就在于 _complete 函数中对 Future 对象和非 Future 对象的两种不一样的处理。对于非 Future 对象,将返回值经过 _setValue 传递给 result ,再分发给其 listener ,这是一个比较常规的过程。而对于 Future 对象也有两种不一样的处理,当返回值是一个 _Future 对象时,调用 _chainCoreFuture ,不然调用 _chainForeignFuture ,这两个函数功能上大同小异,只不过对于 Flutter 默认实现的 _Future,有一些更“本土化”的处理,而对于其余 Future 的实现,则只能使用 Future 带有的函数来实现一样的功能,所谓的处理,就是 Future 不能做为 listener 的返回值出现,具体看代码:async
static void _chainForeignFuture(Future source, _Future target) {
assert(!target._isComplete);
assert(source is! _Future);
// Mark the target as chained (and as such half-completed).
target._setPendingComplete();
try {
source.then((value) {
assert(target._isPendingComplete);
// The "value" may be another future if the foreign future
// implementation is mis-behaving,
// so use _complete instead of _completeWithValue.
target._clearPendingComplete(); // Clear this first, it's set again.
target._complete(value);
},
// TODO(floitsch): eventually we would like to make this non-optional
// and dependent on the listeners of the target future. If none of
// the target future's listeners want to have the stack trace we don't
// need a trace.
onError: (error, [StackTrace stackTrace]) {
assert(target._isPendingComplete);
target._completeError(error, stackTrace);
});
} catch (e, s) {
// This only happens if the `then` call threw synchronously when given
// valid arguments.
// That requires a non-conforming implementation of the Future interface,
// which should, hopefully, never happen.
scheduleMicrotask(() {
target._completeError(e, s);
});
}
}
复制代码
source 是上一个 Future 的返回值,target 是 listener 对应的 Future ,它没有将 source 设置为 target 的 value,而是继续调用 source 的 then 函数,获得 source 的返回值后再调用 target 的 _complete 函数处理返回值,这里便会陷入循环,若是 source 嵌套返回了多少个 Future ,这里就须要调用多少次,总之,直到 source 返回了一个常规的值,才会结束这种循环,这就是 _chainForeignFuture 中所作的处理,只使用到了 Future 的 then 函数,看起来也比较容易理解,不过 _chainCoreFuture 看着就没有这么和善了。ide
static void _chainCoreFuture(_Future source, _Future target) {
assert(target._mayAddListener); // Not completed, not already chained.
while (source._isChained) {
source = source._chainSource;
}
if (source._isComplete) {
_FutureListener listeners = target._removeListeners();
target._cloneResult(source);
_propagateToListeners(target, listeners);
} else {
_FutureListener listeners = target._resultOrListeners;
target._setChained(source);
source._prependListeners(listeners);
}
}
复制代码
首先判断 source 是否处于 Future 链中,若是是,则找到链尾的 Future ,而后将这个 Future 做为 source ,若是 source 已经完成了,把 source 的返回值复制过来,而后分发给 listeners,若是没有,则加入这个 Future 链,并将本身的 listeners 都移植到 source 身上。 那么 Future 链是什么?链尾的 source 又是什么?为何 target 的 listeners 可以直接交给 source ?欢迎来到。。。。 先看几个示例代码:函数
test5() {
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test5");
return "test5";
});
Future(() {
print("return f");
return f;
}).then((String s) => print(s));
}
test6() {
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test6");
return "test6";
});
Future<String> ff = Future(() {
print("return f");
return f;
});
Future<String> fff = Future(() {
print("return ff");
return ff;
});
Future(() {
print("return fff");
return fff;
}).then((String s) => print(s));
}
复制代码
先看 test5 ,首先声明了一个 Future f,延迟 100 ms,接着又定义了一个 Future 会返回 f,它有一个 listener 须要接受 String 参数。当第二个 Future 返回 f 时 f 还未执行完毕,因而此时执行的代码段就是:oop
_FutureListener listeners = target._resultOrListeners;
target._setChained(source);
source._prependListeners(listeners);
复制代码
即 Future 加入了 Future 链,并将 listner 移交给了 f,因此此时实际上的逻辑应该是这样的:ui
test5() {
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test5");
return "test5";
});
f.then((String s) => print(s));
}
复制代码
因而一个双层嵌套的 Future ,变成了一个没有嵌套的 Future,当 f 执行完了以后,就会通知 listner 打印 s。 而对于 test6 ,这是一个多层嵌套,ff、fff 以及最后一个 Future ,返回的都是 Future ,那么当 ff 执行完时,它返回了一个还没有执行完的 f,因此它会加入到 Future 链,此时链为 ff -> f,而后 fff 返回了 ff,而此时 ff 已经在 Future 链中,因此 fff 也会加入 Future 链,此时 fff -> ff -> f,而后就是 Future -> fff -> ff -> f,而且此时 Future 的 listener 挂在了 f 身上,因而也能够化简为:this
test6() {
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test6");
return "test6";
});
f.then((String s) => print(s));
}
复制代码
最终,当 f 执行完了以后,会进入 _complete 函数执行以下代码:
_FutureListener listeners = _removeListeners();
_setValue(value);
_propagateToListeners(this, listeners);
复制代码
此时的 listeners ,即是包含了 ff,fff 和 Future 这三个 Future 的 listener 集合,虽然如此,但此刻它们都已经移植到了 f 身上,而且这个移植是无缝的,从根本上来讲,他们的 listener 实际上监听的也正是 f 的返回值。 看到这里,上面几个问题应该有了解答,Future 链是一串 Future ,可是它们中只有一个 Future 返回了真实的数据,也就是链尾的那一个,前面的 Future 的 listeners 则是直接或间接地依赖着链尾 Future 的返回结果,因此它们的 listeners 也都直接移植到了链尾 Future 上,这个链尾的 Future ,就是 _chainCoreFuture 中的 source,而对于其它那些没有返回真正数据的 Future ,是不会调用它们的 _propagateToListeners 函数的。 _propagateToListeners 负责将返回值传递给 listeners :
static void _propagateToListeners(_Future source, _FutureListener listeners) {
while (true) {
assert(source._isComplete);
bool hasError = source._hasError;
if (listeners == null) {
if (hasError) {
AsyncError asyncError = source._error;
source._zone
.handleUncaughtError(asyncError.error, asyncError.stackTrace);
}
return;
}
// Usually futures only have one listener. If they have several, we
// call handle them separately in recursive calls, continuing
// here only when there is only one listener left.
while (listeners._nextListener != null) {
_FutureListener listener = listeners;
listeners = listener._nextListener;
listener._nextListener = null;
_propagateToListeners(source, listener);
}
_FutureListener listener = listeners;
final sourceResult = source._resultOrListeners;
// Do the actual propagation.
// Set initial state of listenerHasError and listenerValueOrError. These
// variables are updated with the outcome of potential callbacks.
// Non-error results, including futures, are stored in
// listenerValueOrError and listenerHasError is set to false. Errors
// are stored in listenerValueOrError as an [AsyncError] and
// listenerHasError is set to true.
bool listenerHasError = hasError;
var listenerValueOrError = sourceResult;
// Only if we either have an error or callbacks, go into this, somewhat
// expensive, branch. Here we'll enter/leave the zone. Many futures
// don't have callbacks, so this is a significant optimization.
if (hasError || listener.handlesValue || listener.handlesComplete) {
Zone zone = listener._zone;
if (hasError && !source._zone.inSameErrorZone(zone)) {
// Don’t cross zone boundaries with errors.
AsyncError asyncError = source._error;
source._zone
.handleUncaughtError(asyncError.error, asyncError.stackTrace);
return;
}
Zone oldZone;
if (!identical(Zone.current, zone)) {
// Change zone if it's not current.
oldZone = Zone._enter(zone);
}
// These callbacks are abstracted to isolate the try/catch blocks
// from the rest of the code to work around a V8 glass jaw.
void handleWhenCompleteCallback() {
// The whenComplete-handler is not combined with normal value/error
// handling. This means at most one handleX method is called per
// listener.
assert(!listener.handlesValue);
assert(!listener.handlesError);
var completeResult;
try {
completeResult = listener.handleWhenComplete();
} catch (e, s) {
if (hasError && identical(source._error.error, e)) {
listenerValueOrError = source._error;
} else {
listenerValueOrError = new AsyncError(e, s);
}
listenerHasError = true;
return;
}
if (completeResult is Future) {
if (completeResult is _Future && completeResult._isComplete) {
if (completeResult._hasError) {
listenerValueOrError = completeResult._error;
listenerHasError = true;
}
// Otherwise use the existing result of source.
return;
}
// We have to wait for the completeResult future to complete
// before knowing if it’s an error or we should use the result
// of source.
var originalSource = source;
listenerValueOrError = completeResult.then((_) => originalSource);
listenerHasError = false;
}
}
void handleValueCallback() {
try {
listenerValueOrError = listener.handleValue(sourceResult);
} catch (e, s) {
listenerValueOrError = new AsyncError(e, s);
listenerHasError = true;
}
}
void handleError() {
try {
AsyncError asyncError = source._error;
if (listener.matchesErrorTest(asyncError) &&
listener.hasErrorCallback) {
listenerValueOrError = listener.handleError(asyncError);
listenerHasError = false;
}
} catch (e, s) {
if (identical(source._error.error, e)) {
listenerValueOrError = source._error;
} else {
listenerValueOrError = new AsyncError(e, s);
}
listenerHasError = true;
}
}
if (listener.handlesComplete) {
handleWhenCompleteCallback();
} else if (!hasError) {
if (listener.handlesValue) {
handleValueCallback();
}
} else {
if (listener.handlesError) {
handleError();
}
}
// If we changed zone, oldZone will not be null.
if (oldZone != null) Zone._leave(oldZone);
// If the listener’s value is a future we need to chain it. Note that
// this can only happen if there is a callback.
if (listenerValueOrError is Future) {
Future chainSource = listenerValueOrError;
// Shortcut if the chain-source is already completed. Just continue
// the loop.
_Future result = listener.result;
if (chainSource is _Future) {
if (chainSource._isComplete) {
listeners = result._removeListeners();
result._cloneResult(chainSource);
source = chainSource;
continue;
} else {
_chainCoreFuture(chainSource, result);
}
} else {
_chainForeignFuture(chainSource, result);
}
return;
}
}
_Future result = listener.result;
listeners = result._removeListeners();
if (!listenerHasError) {
result._setValue(listenerValueOrError);
} else {
AsyncError asyncError = listenerValueOrError;
result._setErrorObject(asyncError);
}
// Prepare for next round.
source = result;
}
}
复制代码
这个函数相对来讲比较重量级,其完成的功能也是比较多的,不过结构仍是比较清晰的,换算下来就是:
static void _propagateToListeners(_Future source, _FutureListener listeners) {
while (true) {
// 利用递归,将 source 的结果分发给 listeners 中的每个 listener
// 若是 listener 具备这三个之一的能力,就去根据状况执行其中一个
if (hasError || listener.handlesValue || listener.handlesComplete) {
// 声明 handleWhenCompleteCallback 函数
// 声明 handleValueCallback 函数
// 声明 handleError 函数
// 根据 listener 的能力及 source 的执行结果,选择上面的其中一个函数执行
// 若是 listener 的返回结果仍是一个 Future ,那就调用 _chainCoreFuture 或 _chainForeignFuture 进行处理
}
// 若是返回的是一个常规值,则将 value 设置给 result ,接着将 result 的结果分发给 result 的 listeners,因此给 source 和 listeners 从新赋值,while 循环
}
}
复制代码
脉络就是这样。这个函数里面又出现了两种分支,即 listener 处理以后的结果是不是一个 Future ,能够看以下两个示例:
test7() {
print("start");
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test7");
return "test7";
});
Future<String> ff = Future(() {
print("return f");
return f;
});
Future(() {
print("return ff");
return ff;
}).then((String s) {
return Future.delayed(Duration(milliseconds: 100), () {
print("return s");
return s;
});
}).then((String s) => print(s));
print("end");
}
test8() {
print("start");
Future.delayed(Duration(milliseconds: 100), () {
print("return test8");
return "test8";
}).then((String s) {
print("return s1");
return s;
}).then((String s) {
print("return s2");
return s;
}).then((String s) {
print("return s3");
return s;
}).then((String s) {
print(s);
});
print("end");
}
复制代码
在 test7 中,Future 的返回值是 ff ,从上面对 _complete 函数的分析得知,test7 能够作以下转换:
test7() {
print("start");
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test7");
return "test7";
});
f.then((String s) {
return Future.delayed(Duration(milliseconds: 100), () {
print("return s");
return s;
});
}).then((String s) => print(s));
print("end");
}
复制代码
那么当 f 执行完毕的时候,便会经过 _propagateToListeners 将返回结果传递给 listener ,接着执行 listener 的 callback,可是 listener 的返回结果仍是一个 Future ,则会执行这一段代码:
if (listenerValueOrError is Future) {
Future chainSource = listenerValueOrError;
// Shortcut if the chain-source is already completed. Just continue
// the loop.
_Future result = listener.result;
if (chainSource is _Future) {
if (chainSource._isComplete) {
listeners = result._removeListeners();
result._cloneResult(chainSource);
source = chainSource;
continue;
} else {
_chainCoreFuture(chainSource, result);
}
} else {
_chainForeignFuture(chainSource, result);
}
return;
}
复制代码
因此,test7 又会变成以下这样:
test7() {
print("start");
Future<String> f = Future.delayed(Duration(milliseconds: 100), () {
print("return test7");
return "test7";
});
f.then((String s) {
Future f = Future.delayed(Duration(milliseconds: 100), () {
print("return s");
return s;
});
f.then((String s) => print(s));
return f;
});
print("end");
}
复制代码
至此,当 f 中的 Future 也执行完毕的时候,就会出发最后的 listener ,打印 s。 而对于 test8 ,多个 then 链接在一块儿,且返回的结果都是常规值,则对应着这段代码:
_Future result = listener.result;
listeners = result._removeListeners();
if (!listenerHasError) {
result._setValue(listenerValueOrError);
} else {
AsyncError asyncError = listenerValueOrError;
result._setErrorObject(asyncError);
}
// Prepare for next round.
source = result;
复制代码
result 便是 listener 对应的 Future,listeners 是 result 的 listeners,因此,每当一个 while 循环执行以后,就意味着一个 then 函数的结束,直到全部的 listener 都获得处理。 再来看下 then 函数:
Future<R> then<R>(FutureOr<R> f(T value), {Function onError}) {
Zone currentZone = Zone.current;
if (!identical(currentZone, _rootZone)) {
f = currentZone.registerUnaryCallback<FutureOr<R>, T>(f);
if (onError != null) {
// In checked mode, this checks that onError is assignable to one of:
// dynamic Function(Object)
// dynamic Function(Object, StackTrace)
onError = _registerErrorHandler(onError, currentZone);
}
}
_Future<R> result = new _Future<R>();
_addListener(new _FutureListener<T, R>.then(result, f, onError));
return result;
}
复制代码
_addListener 函数能够看出,Future 的 listener 就是在这个函数中添加的,listener 对应的 Future ,也是在这里建立的,result、callback、onError 将会被构形成 _FutureListener 实例,_addListener 负责将 listener 添加到 Future 上。
void _addListener(_FutureListener listener) {
assert(listener._nextListener == null);
if (_mayAddListener) {
listener._nextListener = _resultOrListeners;
_resultOrListeners = listener;
} else {
if (_isChained) {
// Delegate listeners to chained source future.
// If the source is complete, instead copy its values and
// drop the chaining.
_Future source = _chainSource;
if (!source._isComplete) {
source._addListener(listener);
return;
}
_cloneResult(source);
}
assert(_isComplete);
// Handle late listeners asynchronously.
_zone.scheduleMicrotask(() {
_propagateToListeners(this, listener);
});
}
}
复制代码
通常状况下,listener 会被添加到 Future 的 listeners 中,当 Future 已是 Future 链中的一员时,listener 则会直接被添加到 source 中去,或者当 Future 已经执行完成时,则直接调用 _propagateToListeners 处理。 再来讲说 Future 中经常使用的一些参数,好比 _isChained 、_isComplete 以及 _mayAddListener 这些究竟是怎么肯定的?_chainSource 、_resultOrListeners 这些变量都是些什么? 总的来讲,这些都指向两个变量,_state 和 _resultOrListeners,好比:
bool get _mayComplete => _state == _stateIncomplete;
bool get _isPendingComplete => _state == _statePendingComplete;
bool get _mayAddListener => _state <= _statePendingComplete;
bool get _isChained => _state == _stateChained;
bool get _isComplete => _state >= _stateValue;
bool get _hasError => _state == _stateError;
复制代码
又好比:
AsyncError get _error {
assert(_hasError);
return _resultOrListeners;
}
_Future get _chainSource {
assert(_isChained);
return _resultOrListeners;
}
_FutureListener _removeListeners() {
// Reverse listeners before returning them, so the resulting list is in
// subscription order.
assert(!_isComplete);
_FutureListener current = _resultOrListeners;
_resultOrListeners = null;
return _reverseListeners(current);
}
void _setChained(_Future source) {
assert(_mayAddListener);
_state = _stateChained;
_resultOrListeners = source;
}
void _setValue(T value) {
assert(!_isComplete); // But may have a completion pending.
_state = _stateValue;
_resultOrListeners = value;
}
void _setErrorObject(AsyncError error) {
assert(!_isComplete); // But may have a completion pending.
_state = _stateError;
_resultOrListeners = error;
}
void _cloneResult(_Future source) {
assert(!_isComplete);
assert(source._isComplete);
_state = source._state;
_resultOrListeners = source._resultOrListeners;
}
复制代码
因此,error 、result、chainSource、listeners 实际上都是同一个变量表示的,只不过在不一样的状态下,_resultOrListeners 有着不一样的含义,在 _hasError 状态下,_resultOrListeners 表示 error,在 !_isComplete 状态下,_resultOrListeners 表示 listeners,而在给 _resultOrListeners 设置值的时候,通常也会一并给 _state 赋值。