最近自己在寫一個(gè)獨(dú)立APP, 用flutter開發(fā), 不定期發(fā)布一些踩坑記錄, 這篇文章是用來結(jié)合catcher, 專門用來處理全局錯(cuò)誤的一個(gè)flutter插件.
使用很簡單, 文檔寫的也很詳細(xì), 地址在:
https://pub.flutter-io.cn/packages/catcher
dependencies:
catcher: ^0.3.0
使用需要引用
import 'package:catcher/catcher_plugin.dart';
不過一般只需要在main.dart里進(jìn)行配置就行了
CatcherOptions debugOptions = CatcherOptions(DialogReportMode(), [
PostHandler(HttpRequestType.post,
Uri.parse(Api.ERROR_REPORT_URL),
printLogs: true)
]);
CatcherOptions releaseOptions = CatcherOptions(PageReportMode(), [
ConsoleHandler(),
PostHandler(HttpRequestType.post,
Uri.parse(Api.ERROR_REPORT_URL))
]);
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) {
Catcher(ProviderNode(child: MyApp(), providers: providers), debugConfig: debugOptions, releaseConfig: releaseOptions);
});
因?yàn)槲遗渲昧薖rovider 所以這么寫, 如果沒使用的直接用Cather(runApp(MyApp))就行
CatcherOptions 可以配置多個(gè), 對應(yīng)不同時(shí)期使用的策略
PostHandler是我自己重新寫的提交到服務(wù)器的策略,
對MyAPp里的build進(jìn)行配置, 可以構(gòu)建公共的錯(cuò)誤頁面
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
final router = Router();
Routes.configureRoutes(router);
Application.router = router;
return MaterialApp(
title: 'xxx',
debugShowCheckedModeBanner: false,
navigatorKey: Catcher.navigatorKey,
builder: (BuildContext context, Widget widget) {
Catcher.addDefaultErrorWidget(
showStacktrace: false,
customTitle: "十分抱歉, 程序出現(xiàn)錯(cuò)誤",
customDescription: "希望你能將這個(gè)錯(cuò)誤報(bào)告給我們, 以此來幫助我們更好的改進(jìn), 你的幫助是我們前進(jìn)的動力.");
return widget;
},
onGenerateRoute: Application.router.generator,
theme: ThemeData(
primaryColor: Colors.lightBlueAccent,
),
home: SplashPage());
}
}
import 'package:catcher/catcher_plugin.dart';
import 'package:catcher/utils/catcher_utils.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
class PostHandler extends ReportHandler {
final Dio _dio = Dio();
final Logger _logger = Logger("HttpHandler");
final HttpRequestType requestType;
final Uri endpointUri;
Map<String, dynamic> headers = {};
final int requestTimeout;
final int responseTimeout;
final bool printLogs;
PostHandler(this.requestType, this.endpointUri,
{this.requestTimeout = 5000,
this.responseTimeout = 5000,
this.printLogs = false}) {
assert(this.requestType != null, "Request type can't be null");
assert(this.endpointUri != null, "Endpoint uri can't be null");
}
@override
Future<bool> handle(Report error) async {
if (!(await CatcherUtils.isInternetConnectionAvailable())) {
_printLog("No internet connection available");
return false;
}
if (requestType == HttpRequestType.post) {
return _sendPost(error);
}
return true;
}
_printLog(String log) {
if (printLogs) {
_logger.info(log);
}
}
//發(fā)送請求上傳錯(cuò)誤信息
Future<bool> _sendPost(Report error) async {
//獲取應(yīng)用信息
try {
var json = error.toJson();
Options options = Options(
sendTimeout: requestTimeout,
receiveTimeout: responseTimeout,
headers: headers);
Response response = await _dio
.post(endpointUri.toString(), data: json, options: options);
_printLog(
"HttpHandler response status: {response.data}");
return SynchronousFuture(true);
} catch (error, stackTrace) {
return SynchronousFuture(false);
}
}
}