家里老人用手机总怕点错,一不小心就闪退。前两天我爸用微信看新闻,刚要点分享,App直接黑屏退出,气得他直摇头:这玩意儿不靠谱!其实在开发里,这类问题很常见,尤其是Flutter写的App。好在我们能提前“设防”,把异常抓住,不让它影响体验。
全局异常捕获,像装个漏电保护器
家里的电器多了,总得装个漏保,万一短路不至于全家停电。Flutter里也一样,加个全局异常捕获,能让程序不直接崩。
void main() {
// 捕获未处理的 Dart 异常
FlutterError.onError = (FlutterErrorDetails details) {
FlutterError.dumpErrorToConsole(details);
logError(details.exception, details.stackTrace);
};
// 捕获未被 try-catch 的异步错误
PlatformDispatcher.instance.onException = (exception, stack) {
logError(exception, stack);
return true; // 阻止默认行为(如崩溃)
};
runApp(MyApp());
};
void logError(dynamic exception, StackTrace stack) {
// 可以上报到服务器,比如 sentry 或自建日志系统
print('捕获异常:$exception');
print('堆栈信息:$stack');
};
这段代码就像给App安了监控,哪怕某个页面出错,也能记录下来,而不是让用户一脸懵地回到桌面。
网络请求别让小毛病变大问题
做饭时水开忘了关火容易出事,网络请求也一样。一个接口挂了,不该让整个页面瘫痪。用 try-catch 包一下,出错了就给个提示,别硬撑。
Future<void> fetchData() async {
try {
final response = await http.get(Uri.parse('https://api.example.com/data'));
if (response.statusCode == 200) {
// 处理数据
} else {
throw Exception('请求失败:状态码 ${response.statusCode}');
}
} on SocketException catch (e) {
showToast('网络不通,请检查Wi-Fi或流量');
logError(e, StackTrace.current);
} on FormatException catch (e) {
showToast('数据格式出错,稍后再试');
logError(e, StackTrace.current);
} catch (e, s) {
showToast('出了一点小问题,已记录');
logError(e, s);
}
};
这样就算服务器抽风,用户也能知道发生了什么,而不是盯着白屏发愣。
UI层也要有容错心
有时候列表数据没加载完,长度是空的,但代码却去取第0项,啪,崩了。这种低级错误其实很好防。
ListView.builder(
itemCount: data?.length ?? 0,
itemBuilder: (context, index) {
// 先判断数据是否存在
if (data == null || index >= data.length) {
return Container(); // 返回空白或占位
}
return Text(data[index]);
},
);
多写个判断,省得用户因为一条脏数据整个App翻车。
做App和过日子差不多,不怕小问题,就怕没准备。把异常捕获做好,哪怕哪天后端接口改了、网络突然断了,用户也能顺顺当当继续用,不会觉得这软件“不靠谱”。毕竟谁也不想,看个菜谱还得提心吊胆。”