日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

技术实践第二期|Flutter异常捕获

發布時間:2024/8/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 技术实践第二期|Flutter异常捕获 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介:應用性能穩定是良好用戶體驗中非常關鍵的一環,為了更好保障應用性能穩定,異常捕獲在保證線上產品穩定中扮演著至關重要的角色。我們團隊在推出了U-APM移動應用性能監控的產品后,幫助開發者定位并解決掉很多線上的疑難雜癥。隨著使用人數的增多,關注度的提高,在拜訪客戶和開發者的留言中,很多開發者都提出希望該產品可以支持flutter框架的異常捕獲。本身我并沒有做過flutter開發,所以主要是通過在現有產品能力基礎上做插件實現異常的上報,這篇文章就記錄我學習flutter錯誤處理的過程和遇到的問題。

作者:友盟+技術專家 彥克

一、背景

應用性能穩定是良好用戶體驗中非常關鍵的一環,為了更好保障應用性能穩定,異常捕獲在保證線上產品穩定中扮演著至關重要的角色。我們團隊在推出了U-APM移動應用性能監控的產品后,幫助開發者定位并解決掉很多線上的疑難雜癥。隨著使用人數的增多,關注度的提高,在拜訪客戶和開發者的留言中,很多開發者都提出希望該產品可以支持flutter框架的異常捕獲。本身我并沒有做過flutter開發,所以主要是通過在現有產品能力基礎上做插件實現異常的上報,這篇文章就記錄我學習flutter錯誤處理的過程和遇到的問題。

二、Flutter異常

Flutter 異常指的是,Flutter 程序中 Dart 代碼運行時意外發生的錯誤事件。

三、Flutter異常特點

Dart是單進程機制,所以在這個進程中出現問題時僅僅會影響當前進程,Dart 采用事件循環的機制來運行任務,當某個任務發生異常并沒有被捕獲時,程序并不會退出,而直接導致的結果是當前任務的后續代碼就不會被執行了,也就是說一個任務中的異常是不會影響其它任務執行的,各個任務的運行狀態是互相獨立的。

如:我們可以通過與 Java 類似的 try-catch 機制來捕獲它。但與 Java 不同的是,Dart 程序不強制要求我們必須處理異常。

四、Flutter異常分類

在Flutter開發中,根據異常來源的不同,可以將異常分為Framework異常和App異常。Flutter對這兩種異常提供了不同的捕獲方式,Framework異常是由Flutter框架引發的異常,通常是由于錯誤的應用代碼造成Flutter框架底層的異常判斷引起的。而對于App異常,就是應用代碼的異常,通常由未處理應用層其他模塊所拋出的異常引起。根據異常代碼的執行時序,App 異常可以分為兩類,即同步異常和異步異常。

五、捕獲方式

1.App 異常的捕獲方式

捕獲同步異常使用try-catch 機制:

// 使用 try-catch 捕獲同步異常

try {

?throw StateError('This is a Dart exception.');

}

catch(e) {

?print(e);

}

捕獲異步異常使用Future 提供的 catchError 語句:

// 使用 catchError 捕獲異步異常

Future.delayed(Duration(seconds: 1))

? ?.then((e) => throw StateError('This is a Dart exception in Future.'))

? ?.catchError((e)=>print(e));

看到這里估計很多人心里會問,就不能有一種方式既可以監控同步又可以監控異步異常嗎?

答案是有的。

Flutter 提供了 Zone.runZoned 方法來管理代碼中的所有異常。我們可以給代碼執行對象指定一個Zone,在 Dart 中,Zone 表示一個代碼執行的環境范圍,其概念類似沙盒,不同沙盒之間是互相隔離的。如果我們想要觀察沙盒中代碼執行出現的異常,沙盒提供了 onError 回調函數,攔截那些在代碼執行對象中的未捕獲異常。廢話不多說,

Show me the code

runZoned(() {

?// 同步異常

?throw StateError('This is a Dart exception.');

}, onError: (dynamic e, StackTrace stack) {

?print('Sync error caught by zone');

});

runZoned(() {

?// 異步異常

?Future.delayed(Duration(seconds: 1))

? ? ?.then((e) => throw StateError('This is a Dart exception in Future.'));

}, onError: (dynamic e, StackTrace stack) {

?print('Async error aught by zone');

});

為了能夠集中捕獲 Flutter 應用中的未處理異常,最終我把main函數中的 runApp 語句也放置在 Zone 中。這樣在檢測到代碼中運行異常時,就能根據獲取到的異常上下文信息,進行統一處理了:

runZoned>(() async {

?runApp(MyApp());

}, onError: (error, stackTrace) async {

//Do sth for error

});

2.Framework異常捕獲方式

Flutter 框架為我們在很多關鍵的方法進行了異常捕獲。如果我們想自己上報異常,只需要提供一個自定義的錯誤處理回調即可,如:

void main() {

?FlutterError.onError = (FlutterErrorDetails details) {

? ?reportError(details);

?};

...

}

有沒有一套從天而降的代碼,能夠統一處理以上異常呢?

3.總結(一套代碼捕獲所有異常)

runZonedGuarded(() async {

? ?WidgetsFlutterBinding.ensureInitialized();

FlutterError.onError = (FlutterErrorDetails details) {

? ? ?myErrorsHandler.onError(details.exception,details.stack);

? ?};

? ?runApp(MyApp());

?}, (Object error, StackTrace stack) {

? ?myErrorsHandler.onError(error, stack);

?});

代碼中出現了一句,上訴從沒有出現過的代碼即WidgetsFlutterBinding.ensureInitialized(),當我把這行代碼注釋掉的時候,框架異常是捕獲不到的。

當時困擾了好久最后終于查到了原因:

上圖是Flutter的架構層,WidgetFlutterBinding用于與 Flutter 引擎交互。 我們的APM產品需要調用 native 代碼來初始化,并且由于插件需要使用平臺 channel 來調用 native 代碼,這是異步完成的,因此必須調用ensureInitialized()確保你有一個 WidgetsBinding 的實例.

來自 docs :

Returns an instance of the WidgetsBinding, creating and initializing it if necessary. If one is created, it will be a WidgetsFlutterBinding. If one was previously initialized, then it will at least implement WidgetsBinding.

注:如果你的應用在runApp 中調用了 WidgetsFlutterBinding.ensureInitialized() 方法來進行一些初始化操作,則必須在runZonedGuarded中調用WidgetsFlutterBinding.ensureInitialized()

六、異常上報

異常上報的整體方案是通過已有的插件增加接口,橋接Android APM 和 iOS APM庫的自定義異常上報接口。

插件增加函數

static void postException(error, stack) {

? ?List args = [error,stack];

? ?//將異常和堆棧上報至umapm

? ?_channel.invokeMethod("postException",args);

?}

Android 端調用自定義異常上報:

private void postException(List args){

? ?String error = (String)args.get(0);

? ?String stack = (String)args.get(1);

? ?UMCrash.generateCustomLog(stack,error);

?}

iOS端調用自定義異常上報:

if ([@"postException" isEqualToString:call.method]){

? ? ? ?NSString* error = arguments[0];

? ? ? ?NSString* stack = arguments[1];

? ? ? ?[UMCrash reportExceptionWithName:@"Flutter" reason:error stackTrace:stack terminateProgram:NO];

}

以上就是本期干貨內容的介紹,希望我們的技術內容可以更好地幫助開發者們解決問題,我們將陪伴開發者們一起進步,一起成長。

原文鏈接
本文為阿里云原創內容,未經允許不得轉載。

總結

以上是生活随笔為你收集整理的技术实践第二期|Flutter异常捕获的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。