亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android?Flutter中異常處理的方法總結(jié)

 更新時間:2023年06月28日 08:59:01   作者:97令山  
這篇文章主要為大家詳細(xì)介紹了Android?Flutter中異常處理的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

Flutter如何捕獲異常

程序異常會怎樣

  • 在Java中,程序發(fā)生異常且沒有被捕獲,那么程序?qū)K止。
  • 但在Dart或JavaScript中則不會,究其原因,這和它們的運(yùn)行機(jī)制有關(guān)系,Java是多線程模型的編程語言,任意一個線程觸發(fā)異常且沒被捕獲時,整個進(jìn)程就退出。
  • 但Dart和JavaScript不會,它們都是單線程模型,運(yùn)行機(jī)制很相似(但有區(qū)別)。

flutter如何捕獲異常

Dart中可以通過try/catch/finally來捕獲代碼塊異常,這個和其它編程語言類似。

Flutter框架異常捕獲

Flutter 框架在很多關(guān)鍵的方法進(jìn)行了異常捕獲。

舉一個例子,當(dāng)布局發(fā)生越界或不合規(guī)范時,F(xiàn)lutter就會自動彈出一個錯誤界面,這是因?yàn)镕lutter已經(jīng)在執(zhí)行build方法時添加了異常捕獲。

最終的源碼如下,具體看 ComponentElement 類中的 performRebuild() 方法。

@override
void performRebuild() {
  try {
    //執(zhí)行build方法  
    built = build();
  } catch (e, stack) {
    // 有異常時則彈出錯誤提示  
    built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
  } 
}      

可以看到,在發(fā)生異常時,F(xiàn)lutter默認(rèn)的處理方式是彈一個ErrorWidget

但如果想自己捕獲異常并上報到報警平臺的話應(yīng)該怎么做?進(jìn)入_debugReportException()方法看看:

FlutterErrorDetails _debugReportException(
  String context,
  dynamic exception,
  StackTrace stack, {
  InformationCollector informationCollector
}) {
  //構(gòu)建錯誤詳情對象  
  final FlutterErrorDetails details = FlutterErrorDetails(
    exception: exception,
    stack: stack,
    library: 'widgets library',
    context: context,
    informationCollector: informationCollector,
  );
  //報告錯誤 
  FlutterError.reportError(details);
  return details;
}

發(fā)現(xiàn),錯誤是通過FlutterError.reportError方法上報的,繼續(xù)跟蹤:

static void reportError(FlutterErrorDetails details) {
  ...
  if (onError != null)
    onError(details); //調(diào)用了onError回調(diào)
}

發(fā)現(xiàn)onErrorFlutterError的一個靜態(tài)屬性,它有一個默認(rèn)的處理方法 dumpErrorToConsole,到這里就清晰了,如果想自己上報異常,只需要提供一個自定義的錯誤處理回調(diào)即可,如:

void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    reportError(details);
  };
 ...
}

這樣就可以處理那些Flutter為我們捕獲的異常了,接下來看看如何捕獲其它異常。

其它異常捕獲與日志收集

在Flutter中,還有一些Flutter沒有為我們捕獲的異常,如調(diào)用空對象方法異常、Future中的異常。

在Dart中,異常分兩類:同步異常和異步異常,同步異??梢酝ㄟ^try/catch捕獲,而異步異常則比較麻煩,如下面的代碼是捕獲不了Future的異常的:

try{
    Future.delayed(Duration(seconds: 1)).then((e) => Future.error("xxx"));
}catch (e){
    print(e)
}

Dart中有一個runZoned(...) 方法,可以給執(zhí)行對象指定一個Zone。

  • Zone表示一個代碼執(zhí)行的環(huán)境范圍,為了方便理解,可以將Zone類比為一個代碼執(zhí)行沙箱,不同沙箱的之間是隔離的,沙箱可以捕獲、攔截或修改一些代碼行為。
  • 如Zone中可以捕獲日志輸出、Timer創(chuàng)建、微任務(wù)調(diào)度的行為,同時Zone也可以捕獲所有未處理的異常。
  • 下面看看runZoned(...)方法定義:
R runZoned<R>(R body(), {
    Map zoneValues, 
    ZoneSpecification zoneSpecification,
    Function onError,
}) 

zoneValues: Zone 的私有數(shù)據(jù),可以通過實(shí)例zone[key]獲取,可以理解為每個“沙箱”的私有數(shù)據(jù)。

zoneSpecification:Zone的一些配置,可以自定義一些代碼行為,比如攔截日志輸出行為等,舉個例子:

下面是攔截應(yīng)用中所有調(diào)用print輸出日志的行為。

main() {
    runZoned(() => runApp(MyApp()), zoneSpecification: new ZoneSpecification(
        print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
          parent.print(zone, "Intercepted: $line");
        }),
    );
}

這樣一來,APP中所有調(diào)用print方法輸出日志的行為都會被攔截,通過這種方式,也可以在應(yīng)用中記錄日志,等到應(yīng)用觸發(fā)未捕獲的異常時,將異常信息和日志統(tǒng)一上報。ZoneSpecification還可以自定義一些其他行為,讀者可以查看API文檔。

onError:Zone中未捕獲異常處理回調(diào),如果開發(fā)者提供了onError回調(diào)或者通過ZoneSpecification.handleUncaughtError指定了錯誤處理回調(diào),那么這個zone將會變成一個error-zone,該error-zone中發(fā)生未捕獲異常(無論同步還是異步)時都會調(diào)用開發(fā)者提供的回調(diào),如:

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

結(jié)合上面的FlutterError.onError就可以捕獲我們Flutter應(yīng)用中全部錯誤了!需要注意的是,error-zone內(nèi)部發(fā)生的錯誤是不會跨越當(dāng)前error-zone的邊界的,如果想跨越error-zone邊界去捕獲異常,可以通過共同的“源”zone來捕獲,如:

var future = new Future.value(499);
runZoned(() {
	var future2 = future.then((_) { throw "error in first error-zone"; });
	runZoned(() {
		var future3 = future2.catchError((e) { print("Never reached!"); });
	}, onError: (e) { print("unused error handler"); });
}, onError: (e) { print("catches error of first error-zone."); });

總結(jié)

最終異常捕獲和上報代碼如下:

void collectLog(String line){
    ... //收集日志
}
void reportErrorAndLog(FlutterErrorDetails details){
    ... //上報錯誤和日志邏輯
}
FlutterErrorDetails makeDetails(Object obj, StackTrace stack){
    ...// 構(gòu)建錯誤信息
}
void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    reportErrorAndLog(details);
  };
  runZoned(
    () => runApp(MyApp()),
    zoneSpecification: ZoneSpecification(
      print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
        collectLog(line); // 收集日志
      },
    ),
    onError: (Object obj, StackTrace stack) {
      var details = makeDetails(obj, stack);
      reportErrorAndLog(details);
    },
  );
}

到此這篇關(guān)于Android Flutter中異常處理的方法總結(jié)的文章就介紹到這了,更多相關(guān)Android Flutter異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論