1. 页面异常监测
在Flutter中,通常用FlutterError监测Flutter框架抛出的异常,用runZonedGuarded监测应用中用户代码异常。
class AppGuarded {
run(Widget app) {
//1. 用FlutterError监测flutter框架抛出的异常
FlutterError.onError = (FlutterErrorDetails details) async {
//线上环境,将异常交给zone统一处理
if (kReleaseMode) {
Zone.current.handleUncaughtError(details.exception, details.stack!);
} else {
//开发期间,走Console抛出
FlutterError.dumpErrorToConsole(details);
}
};
//2. runZonedGuarded监测整个用应用代码异常 不使用FlutterError默认只能捕捉业务代码异常
runZonedGuarded(() {
runApp(app);
}, (e, s) => _reportError(e, s));
}
///通过接口上报异常
_reportError(Object error, StackTrace s) {
print('kReleaseMode:$kReleaseMode');
print('catch error:$error');
}
}
2. 监测页面流畅性(帧率)
帧率监测在Flutter中通常通过在SchedulerBinding中注册fps相关回调来实现。通常需要保留最近若干个FrameTiming的总耗时,计算其平均值,以消除不必要数据波动。
void start() {
SchedulerBinding.instance.addTimingsCallback(_onReportTimings);
}
// 不需监听时移除
void stop() {
SchedulerBinding.instance.removeTimingsCallback(_onReportTimings);
}
void _onReportTimings(List<FrameTiming> timings) {
// TODO
}
3. 页面显示耗时(FCP)
记录页面初始化和首次上屏时间,然后计算其时间差即可。
@override
initState() {
super.initState();
//1. 记录页面创建时间
double startTime = time(0);
//2.注册首帧显示时间回调
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
double endTime = time(0);
print('WidgetsBinding Test-${(context as Element).size}');
});
4. 页面PV监测
页面PV监测核心是检测到页面栈的变化,以便统计出页面曝光次数。如果应用采用自定义导航框架,只需在导航框架正确位置添加埋点即可。若采用的是系统默认的导航框架,则可通过继承NavigatorObserver,捕获Navigator的didPush和didPop回调。
//导航栈的变化监听
class MyNavigator extends NavigatorObserver{
@override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
super.didPop(route, previousRoute);
var previousName = '';
if (previousRoute == null) {
previousName = 'null';
}else {
previousName = previousRoute.settings.name;
}
print('YM----->NavObserverDidPop--Current:' + route.settings.name + ' Previous:' + previousName);
}
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
super.didPush(route, previousRoute);
var previousName = '';
if (previousRoute == null) {
previousName = 'null';
}else {
previousName = previousRoute.settings.name;
}
print('YM-------NavObserverDidPush-Current:' + route.settings.name + ' Previous:' + previousName);
}