Flutter 之異常捕獲

1斋荞、Dart 單線程模型

在 Java 和 Objective-C(以下簡(jiǎn)稱 OC )中,如果程序發(fā)生異常且沒(méi)有被捕獲,那么程序?qū)?huì)終止床绪,但是這在 Dart 或 JavaScript 中則不會(huì)机杜。這是因?yàn)?Java 和 OC 都是多線程模型的編程語(yǔ)言帜讲,任意一個(gè)線程觸發(fā)異常且該異常未被捕獲時(shí),就會(huì)導(dǎo)致整個(gè)進(jìn)程退出椒拗。而 Dart 和 JavaScript 都是單線程模型似将。

Dart 運(yùn)行原理

解析
1获黔、Dart 在單線程中是以消息循環(huán)機(jī)制來(lái)運(yùn)行的。其包含兩個(gè)隊(duì)列在验,一個(gè)是微任務(wù)隊(duì)列(microtask queue)玷氏,另一個(gè)是事件隊(duì)列(event queue)。并且微任務(wù)隊(duì)列的執(zhí)行優(yōu)先級(jí)高于事件隊(duì)列腋舌。
2盏触、Dart 線程的運(yùn)行,在入口函數(shù) main() 執(zhí)行完后块饺,消息循環(huán)機(jī)制便啟動(dòng)了赞辩。首先會(huì)按照先進(jìn)先出的順序逐個(gè)執(zhí)行微任務(wù)隊(duì)列(microtask queue)中的任務(wù),然后是事件隊(duì)列(event queue)中的任務(wù)授艰,待事件隊(duì)列中的任務(wù)執(zhí)行完畢后程序便會(huì)退出辨嗽。但是,在事件任務(wù)執(zhí)行的過(guò)程中也可以插入新的微任務(wù)和事件任務(wù)淮腾,在這種情況下糟需,整個(gè)線程的執(zhí)行過(guò)程便是一直在循環(huán),不會(huì)退出来破,而 Flutter 中篮灼,主線程的執(zhí)行過(guò)程正是如此,永不終止徘禁。
3诅诱、在 Dart 中,所有的外部事件任務(wù)都在事件隊(duì)列中送朱,如 IO娘荡、計(jì)時(shí)器、點(diǎn)擊驶沼、以及繪制事件等炮沐。而微任務(wù)通常來(lái)源于 Dart 內(nèi)部,并且微任務(wù)非常少回怜,之所以如此大年,是因?yàn)槲⑷蝿?wù)隊(duì)列優(yōu)先級(jí)高,如果微任務(wù)太多玉雾,執(zhí)行時(shí)間總和就越久翔试,事件隊(duì)列任務(wù)的延遲也就越久,對(duì)于 GUI 應(yīng)用來(lái)說(shuō)最直觀的表現(xiàn)就是比較卡复旬,所以必須得保證微任務(wù)隊(duì)列不會(huì)太長(zhǎng)垦缅。注意注意,可以通過(guò)Future.microtask(…)方法向微任務(wù)隊(duì)列插入一個(gè)任務(wù)驹碍。
4壁涎、在事件循環(huán)中凡恍,當(dāng)某個(gè)任務(wù)發(fā)生異常并沒(méi)有被捕獲時(shí),程序并不會(huì)退出怔球,而直接導(dǎo)致的結(jié)果是當(dāng)前任務(wù)的后續(xù)代碼就不會(huì)被執(zhí)行了嚼酝,也就是說(shuō)一個(gè)任務(wù)中的異常是不會(huì)影響其他任務(wù)執(zhí)行的。
5庞溜、Dart 中也可以通過(guò) try/catch/finally 來(lái)捕獲代碼塊異常革半。

2碑定、Flutter 中的異常捕獲

1流码、Flutter 框架異常捕獲

Flutter 框架在很多關(guān)鍵的方法進(jìn)行了異常捕獲。如:布局發(fā)生越界或不合規(guī)范時(shí)延刘,F(xiàn)lutter 就會(huì)自動(dòng)彈出一個(gè)錯(cuò)誤界面(ErrorWidget)漫试,這是因?yàn)?Flutter 已經(jīng)在執(zhí)行 build 方法時(shí)添加了異常捕獲。其源碼如下:

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

異常上報(bào)
通過(guò) FlutterError 中一個(gè)靜態(tài)屬性 onError 的一個(gè)默認(rèn)處理方法 dumpErrorToConsole 來(lái)實(shí)現(xiàn)異常上報(bào)碘赖。

void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    reportError(details);
  };
 ...
}
2驾荣、其他異常捕獲與日志收集

在 Flutter 中,有一些 Flutter 沒(méi)有捕獲的異常普泡,如:調(diào)用空對(duì)象方法異常播掷、Future 中的異常。在 Dart 中撼班,異常分為同步異常和異步異常歧匈,同步異常可以通過(guò) try/catch 捕獲砰嘁;而異步異常則比較麻煩件炉,如下面的代碼是捕獲不了 Future 異常的:

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

可以通過(guò) onError + runZoned(...) 方法來(lái)實(shí)現(xiàn)異常捕獲和日志上報(bào)

void collectLog(String line){
    //收集日志
}
void reportErrorAndLog(FlutterErrorDetails details){
    //上報(bào)錯(cuò)誤和日志邏輯
}

FlutterErrorDetails makeDetails(Object obj, StackTrace stack){
    // 構(gòu)建錯(cuò)誤信息
}

void main() {
  var onError = FlutterError.onError; //先將 onerror 保存起來(lái)
  FlutterError.onError = (FlutterErrorDetails details) {
    onError?.call(details); //調(diào)用默認(rèn)的onError
    reportErrorAndLog(details); //上報(bào)
  };
  runZoned(
  () => runApp(MyApp()),
  zoneSpecification: ZoneSpecification(
    // 攔截print
    print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
      collectLog(line);
      parent.print(zone, "Interceptor: $line");
    },
    // 攔截未處理的異步錯(cuò)誤
    handleUncaughtError: (Zone self, ZoneDelegate parent, Zone zone,
                          Object error, StackTrace stackTrace) {
      reportErrorAndLog(details);
      parent.print(zone, '${error.toString()} $stackTrace');
    },
  ),
 );
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矮湘,隨后出現(xiàn)的幾起案子斟冕,更是在濱河造成了極大的恐慌,老刑警劉巖缅阳,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磕蛇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡十办,警方通過(guò)查閱死者的電腦和手機(jī)秀撇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)橘洞,“玉大人捌袜,你說(shuō)我怎么就攤上這事≌ㄔ妫” “怎么了虏等?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵弄唧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我霍衫,道長(zhǎng)候引,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任敦跌,我火速辦了婚禮澄干,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘柠傍。我一直安慰自己麸俘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布惧笛。 她就那樣靜靜地躺著从媚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪患整。 梳的紋絲不亂的頭發(fā)上拜效,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音各谚,去河邊找鬼紧憾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛昌渤,可吹牛的內(nèi)容都是我干的赴穗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼愈涩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼望抽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起履婉,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤煤篙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后毁腿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體辑奈,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年已烤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鸠窗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胯究,死狀恐怖稍计,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情裕循,我是刑警寧澤臣嚣,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布净刮,位于F島的核電站,受9級(jí)特大地震影響硅则,放射性物質(zhì)發(fā)生泄漏淹父。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一怎虫、第九天 我趴在偏房一處隱蔽的房頂上張望暑认。 院中可真熱鬧,春花似錦大审、人聲如沸蘸际。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捡鱼。三九已至,卻和暖如春酷愧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缠诅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工溶浴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人管引。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓士败,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親褥伴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谅将,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 跟隨《Flutter實(shí)戰(zhàn)·第二版》[https://book.flutterchina.club]學(xué)習(xí),建議直接看...
    QYCD閱讀 359評(píng)論 0 0
  • 本文內(nèi)容非原創(chuàng), 僅用于整理記錄原文鏈接??: flutter 崩潰收集 Dart線程模型及異常捕獲 Flutter...
    _白羊閱讀 8,231評(píng)論 4 5
  • 在程序開(kāi)發(fā)中重慢,有個(gè)非常重要的思想饥臂,《發(fā)現(xiàn)問(wèn)題,解決問(wèn)題》異常捕獲顯然是發(fā)現(xiàn)問(wèn)題似踱,解決問(wèn)題的必要手段之一隅熙,接下來(lái)我們...
    YorkLe閱讀 316評(píng)論 0 0
  • 1.Dart單線程模型 在 Java 和 Objective-C中,如果程序發(fā)生異常且沒(méi)有被捕獲核芽,那么程序?qū)?huì)終止...
    明月夜_e586閱讀 106評(píng)論 0 0
  • 前言 在介紹Flutter異常捕獲之前必須先了解一下Dart單線程模型囚戚,只有了解了Dart的代碼執(zhí)行流程,我們才能...
    沫之閱讀 4,432評(píng)論 0 2