Flutter異常捕獲在項目中的應(yīng)用

image

在程序開發(fā)中啊研,有個非常重要的思想者祖,《發(fā)現(xiàn)問題眶痰,解決問題》異常捕獲顯然是發(fā)現(xiàn)問題恍飘,解決問題的必要手段之一榨崩,接下來我們先了解下flutter的異常捕獲

Flutter異常捕獲

在介紹Flutter異常捕獲之前必須先了解一下Dart單線程模型,只有了解了Dart的代碼執(zhí)行流程章母,我們才能知道該在什么地方去捕獲異常母蛛。

Dart單線程模型

在Java和Objective-C(以下簡稱“OC”)中,如果程序發(fā)生異常且沒有被捕獲乳怎,那么程序?qū)K止彩郊,但是這在Dart或JavaScript中則不會!究其原因,這和它們的運行機制有關(guān)系秫逝。Java和OC都是多線程模型的編程語言恕出,任意一個線程觸發(fā)異常且該異常未被捕獲時,就會導(dǎo)致整個進程退出违帆。但Dart和JavaScript不會浙巫,它們都是單線程模型,運行機制很相似(但有區(qū)別)刷后,下面我們通過Dart官方提供的一張圖來看看Dart大致運行原理:


image

Dart 在單線程中是以消息循環(huán)機制來運行的狈醉,其中包含兩個任務(wù)隊列,一個是“微任務(wù)隊列” microtask queue惠险,另一個叫做“事件隊列” event queue。從圖中可以發(fā)現(xiàn)抒线,微任務(wù)隊列的執(zhí)行優(yōu)先級高于事件隊列班巩。

現(xiàn)在我們來介紹一下Dart線程運行過程,如上圖中所示嘶炭,入口函數(shù) main() 執(zhí)行完后抱慌,消息循環(huán)機制便啟動了。首先會按照先進先出的順序逐個執(zhí)行微任務(wù)隊列中的任務(wù)眨猎,事件任務(wù)執(zhí)行完畢后程序便會退出抑进,但是,在事件任務(wù)執(zhí)行的過程中也可以插入新的微任務(wù)和事件任務(wù)睡陪,在這種情況下寺渗,整個線程的執(zhí)行過程便是一直在循環(huán),不會退出兰迫,而Flutter中信殊,主線程的執(zhí)行過程正是如此,永不終止汁果。

在Dart中涡拘,所有的外部事件任務(wù)都在事件隊列中,如IO据德、計時器鳄乏、點擊、以及繪制事件等棘利,而微任務(wù)通常來源于Dart內(nèi)部橱野,并且微任務(wù)非常少,之所以如此赡译,是因為微任務(wù)隊列優(yōu)先級高仲吏,如果微任務(wù)太多,執(zhí)行時間總和就越久,事件隊列任務(wù)的延遲也就越久裹唆,對于GUI應(yīng)用來說最直觀的表現(xiàn)就是比較卡誓斥,所以必須得保證微任務(wù)隊列不會太長。值得注意的是许帐,我們可以通過Future.microtask(…)方法向微任務(wù)隊列插入一個任務(wù)劳坑。

在事件循環(huán)中,當(dāng)某個任務(wù)發(fā)生異常并沒有被捕獲時成畦,程序并不會退出距芬,而直接導(dǎo)致的結(jié)果是當(dāng)前任務(wù)的后續(xù)代碼就不會被執(zhí)行了,也就是說一個任務(wù)中的異常是不會影響其它任務(wù)執(zhí)行的循帐。

Flutter異常捕獲

Dart中可以通過try/catch/finally來捕獲代碼塊異常框仔,這個和其它編程語言類似,如果讀者不清楚拄养,可以查看Dart語言文檔离斩,不再贅述,下面我們看看Flutter中的異常捕獲瘪匿。

Flutter框架異常捕獲

Flutter 框架為我們在很多關(guān)鍵的方法進行了異常捕獲跛梗。這里舉一個例子,當(dāng)我們布局發(fā)生越界或不合規(guī)范時棋弥,F(xiàn)lutter就會自動彈出一個錯誤界面核偿,這是因為Flutter已經(jīng)在執(zhí)行build方法時添加了異常捕獲,最終的源碼如下:

@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)該怎么做粉寞?我們進入_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)onError是FlutterError的一個靜態(tài)屬性仁锯,它有一個默認(rèn)的處理方法 dumpErrorToConsole耀找,到這里就清晰了,如果我們想自己上報異常业崖,只需要提供一個自定義的錯誤處理回調(diào)即可野芒,如:

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

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

在項目中比較簡單且有效的用法

  Future requestApi() async{
    try{
    // TODO:需要檢查的異常代碼
    ...
    }catch(e){
    // debugger 項目中非常好用狞悲,出現(xiàn)異地直接定位到問題的地方,有奇效妇斤,強力推薦讀者自己試一下debugger()
      debugger(when: e!= null);
      print(e);
    }
  }

本文 部分代碼來源于《Flutter實戰(zhàn)》

《Flutter實戰(zhàn)》比較實用的一本書摇锋,值得入坑購買(https://u.jd.com/7B1kD2)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丹拯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子荸恕,更是在濱河造成了極大的恐慌乖酬,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件融求,死亡現(xiàn)場離奇詭異咬像,居然都是意外死亡,警方通過查閱死者的電腦和手機生宛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門县昂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陷舅,你說我怎么就攤上這事倒彰。” “怎么了莱睁?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵狸驳,是天一觀的道長。 經(jīng)常有香客問我缩赛,道長,這世上最難降的妖魔是什么撰糠? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任酥馍,我火速辦了婚禮,結(jié)果婚禮上阅酪,老公的妹妹穿的比我還像新娘旨袒。我一直安慰自己,他們只是感情好术辐,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布砚尽。 她就那樣靜靜地躺著,像睡著了一般辉词。 火紅的嫁衣襯著肌膚如雪必孤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天瑞躺,我揣著相機與錄音敷搪,去河邊找鬼。 笑死幢哨,一個胖子當(dāng)著我的面吹牛赡勘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捞镰,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼闸与,長吁一口氣:“原來是場噩夢啊……” “哼毙替!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起践樱,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤厂画,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后映胁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體木羹,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年解孙,在試婚紗的時候發(fā)現(xiàn)自己被綠了坑填。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡弛姜,死狀恐怖脐瑰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情廷臼,我是刑警寧澤苍在,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站荠商,受9級特大地震影響寂恬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜莱没,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一初肉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饰躲,春花似錦牙咏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寄狼,卻和暖如春丁寄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泊愧。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工狡逢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拼卵。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓奢浑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腋腮。 傳聞我的和親對象是個殘疾皇子雀彼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355