写在前面

在《Flutter 实战》这本书里的 Flutter异常捕获 一节,讲到了怎样对异步异常进行捕获,里边就提到了用 Zone 来做处理。

Zone表示一个代码实施的环境规划,为了便当了解,读者能够将Zone类比为一个代码实施沙箱,不同沙箱的之间是阻隔的,沙箱能够捕获、阻拦或修改一些代码行为,如Zone中能够捕获日志输出、Timer创建、微使命调度的行为,一起Zone也能够捕获一切未处理的异常。

这一篇首要就是对 Zone 进行一些用法和参数上的了解。服务器

内容

先从异常的比如讲起

在 Flutter 里,同步代码里异常的捕获运用try-catch进行。咱们用await的办法来处理 Future,同样也是同步代码,所以也能够被try-catch捕获:

main() async {flutter支撑鸿蒙吗
try {
throw "My Error服务器内存和一般内存有什么差异";
} catch (e)flutter结构优缺点 {
print(e);
}
try {
await Future.error("My Future Error");
} catch (e) {
prinflutter开发的app有哪些t(e);
}
}

打印作用:

My Error
My Future Error

关于不是这种同步写法的异步过错,那么咱们就需要经过Zone来处理。Zone给代码供应了一个环境,并能捕获到里边的相关信息approach。以《Flutter 实战》一书里给的比如,它经过 Dart 里的runZoned()办法,让当时 Zone fork 一个服务器装备新的 Zone 出来,把代码放在里边实施。

R runZoned<R>(R body(),
{Map<Object?, Object?>? zoneValues,
Zo服务器体系neSpecflutteringification? zoneSpeciapp是什么意思fication,
@Deprecated("Use runZonedGuardflutter是什么意思ed insteadappetite") Function? onError}) {
check服务器操作体系银河麒麟NotNullable(body, "body");
...
return _runZoneappetited<R>(body, zoneVal服务器怎样搭建ues, zoneSpecifiappearancecation);
}服务器体系
R _runZoned<R>(R body(), Map<Object?, Object?>? zoneValues,
ZoneSpecification? s服务器操作体系银河麒麟pecification) =>
ZoFlutterneflutter怎样读音发音.current
.fork(specificationappear: specification, zoneValues: zoneValues)服务器地址在哪里看
.run<R>flutter开发的app有哪些(body);

能够看出runZoned()其实是对flutteredZone.current.fork().run()的一个封装。

所以经过给咱们的整个 App 套上一flutter是什么意思个 Zone,就能够捕获一切的异常了。

runZoned(() {
runApp(MyApp());
}, onError: (Object obFlutterj, StackTrace stack) {
var details=makeDetails(obj,stack);
reportError(details);
});

Zone

main

当咱们作业main()函数的时分,其实就现已作业在一个 rapproachoot 的 Zone 里:

main() {
Zone.ro服务器租借ot.run(() => print("hello"));
print(Zone.root == Zone.current);
}

打印作用:

hello
true

main()里调用Zone.root.run()办法跟直接服务器是什么main()里没差异,并且由于现已默许作业起来,所以咱们也不能对Zone进行一些定制flutter是什么意思修改,这也是服务器租借多少钱一年为什么咱们要新建一个Zone来处理。

参数

Zone 里有几个参数:

  • zoneValues
  • zoneSpecificati服务器内存和一般内存有什么差异on
  • onError

zoneValues

这是 Zone 的私有数据,能够经过实例 zonflutter结构e[key] 获取,flutter结构优缺点并且能够被自己 fo服务器租借rk 出来的子 Zone 继承。

  Zone parentZone = Zone.current.服务器操作体系银河麒麟fork(zoneValues: {"parentValue": 1});
Zone childZone = parentZone.fork();服务器地址在哪里看
// childZone 能够经过父的 key 取appstore得相appreciate应的 value
childZone.rappstoreun(() => {print(childZoneflutter结构优缺点["parentValue"])});

zoneSpecification

Zone的一些配服务器装备备,能够自定义一些代码行为,比如阻拦日志输出行为等。

abstract class ZoneSpecificatioflutter是什么意思n {
...
const factory ZoneSpecification(
{HandleUnc服务器装备auflutter怎样读音发音ghtErrorHand服务器操作体系银河麒麟leflutteringr? h服务器租借andleUncaughtError,
RunHandler? ruappearancen,
RunUnaryHandler? runUnary,
RunBinaryHandler? runBinary,
RegisterCallbackHandler? registerCalappearancelback,
RegisterUnaryCallbacappearancekHandflutter怎样读音发音ler? registerUnaryCallback,
RegisterBinaryCallbackHandler? registerBin服务器怎样搭建aryCallback,
ErrorCallba服务器租借ckHandler? errorCaFlutterllback,
Schedule服务器内存和一般内存有什么差异MicrotaskHandler? scheduleMicrotask,
CreateTimerHandler? createTimer,
CreatePeriodicTimerHandlerFlutter? createPeriodicTimer,
PrintHandler? print,
ForkHandler? fork}) = _ZoneSpe服务器操作体系银河麒麟cification;
...
}
修改 print 行为

比如说在一个 Zone 里,咱们想修改它的 print 行为,就能够flutter结构这样做:

main() {
Zone parentZoneapplication = Zone.current.fork(specification: new ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
parentflutter结构优缺点.print(zone, "Intercepted: $line");
// 还能够在这儿把打印写入文件,发送给服务器
}));
parentZoflutter开发的app有哪些ne.run(() => print("hello"));
print("hello");
}

打印作用:

Intercepted: hello
hello

能够看到当咱们parentZone作业起来后,print 的行为就现已被咱们修改了。

由于终究面的 print 不在同一个 Zone 里,所以这个 print 不会产生appear改动。

修改 run 的行为

假定咱们想在进入run()的时分做一些作业,就能够:

main()flutter怎样读音发音 {
Zone parentfluttershyZone = Zone.current.fork(
specappleification: new ZoneSpecification(
run: <R&flutter支撑鸿蒙吗gt;(self, parent,fluttered zone, f) {
print("Enter run");
re服务器是什么turn parent.run(appstorezone, f);
}));
parentZone.run(() => print("hello")服务器操作体系银河麒麟);
}

打印作用:

Enter run
hello
修改注册回调
main() {
Zone.root;
Zone parentZone =flutter怎样读音发音 Zone.current.for服务器租借多少钱一年k(specification:
new ZoneSpecification(registerCallback: <R>(self, parent, zone, f) {
// 调用咱们实践注册的回调函数,第一次这儿进来的 f 是 start(),第2次进来则是 end()
f();
return f;
}));
parentZone.run(() {
Zone.current.registerCallapplicationbackapple(() => start());
print("hell服务器装备o"appointment);
Zone.current.registerCallback(() => end());
});
}
voflutteringid stflutteringart() {
print("start");
}
void end() {
print("end");
}

打印作用flutter怎样读音发音

start
hello
end

onError

尽管runZoned()办法有onError的回调,但官方新版本里推荐是用runZonedGuarded()来代替:

 r服务器和电脑主机的差异unZonedGuarded(() {
tflutter开发的app有哪些hrow "null";
}, (Object error, StackTrace stack) {
print("error = ${error.toString()}");
});

打印作用

error = null

也就是说在Zone里那些没有被咱们捕服务器租借获的异常,都会走到onError回调里。
那么假定这个Zonespecification里完成了handleUncaughtError或者是完成了onError回调,那么这个 Zone就变成了一个error-zone

那么error-zone里产生的异常是不会跨越距离的,例如:

var future = new Future.valuflutter开发的app有哪些e(499);
var future2 = future.then((_) {throw "future error";});
runZonedGuarded(() {
var future3 = future2.服务器和电脑主机的差异catchErroapproachr((e) {
print(e.服务器装备toString()flutter支撑鸿蒙吗); // 不会打印
});
}, (Object error, StackTrace stack) {
prinappstoret(" error = ${error.toString()}"); // 不会打印
});

future函数在error-zone的外面定义,并定义了实施结束后会抛出异常,当在erroappler-zone里调用的时分,此时这个异常就无法被error-zone捕获了,由于现已超出了它的距离,处理的app是什么意思做法就是在定义future服务器租借多少钱一年数那里再套一个Zone,这样这个过错就会被外面的error-zone捕获了:

  var futu服务器租借re = neappetitew Future.value(499);
runZonedGuarded(() {
var future2 = future.then((_) {
throw "future error";
});
runZonedGuarded(() {
var future3 = future2.catchError((e) {
print(e.toString());
});
}, (Object error, StackTrace stack) {
print(" error = ${error.toString()}");
})app是什么意思;
}, (Objflutter中文官网ect error, StackTrace stack) {
print("out error = ${error.toString()}");
});

输出作用:

out error = future error