Flutter
Flutter - RouteObserver
대기만성 개발자
2022. 9. 8. 13:57
반응형
화면 이동을 tracking 하는 용도로 사용할 때 RouteObserver를 사용하면 간단합니다
void main() {
runApp(MaterialApp(
home: const MyApp(),
navigatorObservers: [CommonRouteObserver()],
));
}
MaterialApp의 navigatorObservers에 등록을 해주고
RouteObserver를 상속받은 클래스의 기능을 정의해줍니다
class CommonRouteObserver extends RouteObserver<PageRoute<dynamic>> {
void _saveScreenView(
{PageRoute<dynamic>? oldRoute,
PageRoute<dynamic>? newRoute,
String? routeType}) {
debugPrint(
'[track] screen old : ${oldRoute?.settings.name}, new : ${newRoute?.settings.name}');
}
PageRoute? checkPageRoute(Route<dynamic>? route) {
return (route is PageRoute) ? route : null;
}
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPush(route, previousRoute);
_saveScreenView(
newRoute: checkPageRoute(route),
oldRoute: checkPageRoute(previousRoute),
routeType: 'push',
);
}
@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
_saveScreenView(
newRoute: checkPageRoute(newRoute),
oldRoute: checkPageRoute(oldRoute),
routeType: 'replace',
);
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
_saveScreenView(
newRoute: checkPageRoute(previousRoute),
oldRoute: checkPageRoute(route),
routeType: 'pop',
);
}
@override
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
_saveScreenView(
newRoute: checkPageRoute(route),
oldRoute: checkPageRoute(previousRoute),
routeType: 'remove',
);
}
}
먼저 자주(?) 사용하는 기능들을 override해서
이전에 기존에 있던 위치 그리고 이동할 위치를 각각 정의해줍니다
여기서 주의할 부분은 didPop은 route가 반대입니다
그리고 테스트에 사용할 view들을 간단하게(?) 만들어봤습니다
// MyApp class
class MyApp extends StatelessWidget {
const MyApp({super.key});
final List<Widget> _list = const [Route1(), Route2()];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('UUID Example'),
),
body: ListView.builder(
itemCount: _list.length,
itemBuilder: (_, index) {
return ListTile(
title: Text('Route - $index'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => _list[index],
settings: RouteSettings(name: '/Route - $index'),
),
);
},
);
},
),
);
}
}
// Route1 class
class Route1 extends StatelessWidget {
const Route1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: const Text('뒤로가기'),
onPressed: () {
Navigator.pop(context);
},
),
));
}
}
// Route2 class
class Route2 extends StatelessWidget {
const Route2({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: const Text('뒤로가기'),
onPressed: () {
Navigator.pop(context);
},
),
));
}
}
이동할 route의 이름을 정의해주는 부분이 있는데
namedRoute를 사용하면 routeSetting부분을 생략해도 됩니다
그리고 간단하게 push/pop 하는 구조로 만들어서 테스트를 해보면
잘 작동하는것을 확인할 수 있습니다
FirebaseAnalytics를 이용하신다면
saveScreenView 부분에
FirebaseAnalytics.instance.logScreenView(screenName: '${newRoute?.settings.name}');
해당 부분을 넣어주면 route가 이동할 때마다 FirebaseAnalytics에 트래킹이 가능합니다
반응형