RouteListenerManager 路由监听管理器
概述
RouteListenerManager
是一个用于管理Flutter应用路由监听器的单例类,它提供了统一的路由事件监听和通知机制。该管理器配合 GlobalRouteObserver
类,能够全局监听应用的路由变化,包括路由跳转、返回、替换和移除等操作。
核心特性
-
单例模式:确保全局只有一个路由监听管理器实例
-
多种路由事件监听:支持路由跳转、返回、替换、移除四种事件类型
-
异常处理:监听器执行过程中的异常不会影响其他监听器
-
全局路由观察 :通过
GlobalRouteObserver
自动捕获所有路由变化 -
灵活管理:支持动态添加、移除监听器
类结构
RouteListenerManager
单例实现
dart
static final RouteListenerManager _instance = RouteListenerManager._internal();
factory RouteListenerManager() => _instance;
static RouteListenerManager get instance => _instance;
RouteListenerManager._internal();
监听器存储
-
_pushListeners
: 路由跳转监听器列表 -
_popListeners
: 路由返回监听器列表 -
_replaceListeners
: 路由替换监听器列表 -
_removeListeners
: 路由移除监听器列表
API 文档
监听器管理方法
添加监听器
addPushListener
dart
void addPushListener(Function(String route) listener)
-
功能:添加路由跳转监听器
-
参数 :
listener
- 接收路由名称的回调函数 -
用途:当发生路由跳转时触发
addPopListener
dart
void addPopListener(Function(String route) listener)
-
功能:添加路由返回监听器
-
参数 :
listener
- 接收路由名称的回调函数 -
用途:当发生路由返回时触发
addReplaceListener
dart
void addReplaceListener(Function(String newRoute, String oldRoute) listener)
-
功能:添加路由替换监听器
-
参数 :
listener
- 接收新路由名称和旧路由名称的回调函数 -
用途:当发生路由替换时触发
addRemoveListener
dart
void addRemoveListener(Function(String route) listener)
-
功能:添加路由移除监听器
-
参数 :
listener
- 接收路由名称的回调函数 -
用途:当发生路由移除时触发
移除监听器
removePushListener
dart
void removePushListener(Function(String route) listener)
- 功能:移除指定的路由跳转监听器
removePopListener
dart
void removePopListener(Function(String route) listener)
- 功能:移除指定的路由返回监听器
removeReplaceListener
dart
void removeReplaceListener(Function(String newRoute, String oldRoute) listener)
- 功能:移除指定的路由替换监听器
removeRemoveListener
dart
void removeRemoveListener(Function(String route) listener)
- 功能:移除指定的路由移除监听器
removeAllListener
dart
void removeAllListener()
-
功能:移除所有类型的监听器
-
用途:清理所有监听器,通常在应用退出时调用
通知方法
notifyPush
dart
void notifyPush(String route)
-
功能:通知所有路由跳转监听器
-
异常处理:单个监听器异常不会影响其他监听器执行
notifyPop
dart
void notifyPop(String route)
-
功能:通知所有路由返回监听器
-
异常处理:单个监听器异常不会影响其他监听器执行
notifyReplace
dart
void notifyReplace(String newRoute, String oldRoute)
-
功能:通知所有路由替换监听器
-
异常处理:单个监听器异常不会影响其他监听器执行
notifyRemove
dart
void notifyRemove(String route)
-
功能:通知所有路由移除监听器
-
异常处理:单个监听器异常不会影响其他监听器执行
GlobalRouteObserver
类定义
dart
class GlobalRouteObserver extends NavigatorObserver
重写方法
didPush
dart
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute)
-
功能:监听路由跳转事件
-
实现 :提取路由名称并调用
RouteListenerManager().notifyPush()
-
日志:输出路由跳转信息
didPop
dart
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute)
-
功能:监听路由返回事件
-
实现 :提取路由名称并调用
RouteListenerManager().notifyPop()
-
日志:输出路由返回信息
didReplace
dart
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute})
-
功能:监听路由替换事件
-
实现 :提取新旧路由名称并调用
RouteListenerManager().notifyReplace()
-
日志:输出路由替换信息
-
安全检查:确保新旧路由都不为空
didRemove
dart
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute)
-
功能:监听路由移除事件
-
实现 :提取路由名称并调用
RouteListenerManager().notifyRemove()
-
日志:输出路由移除信息
使用示例
1. 基本使用
dart
// 获取管理器实例
final routeManager = RouteListenerManager.instance;
// 添加路由跳转监听器
routeManager.addPushListener((String route) {
print('路由跳转到: $route');
// 执行自定义逻辑,如埋点统计、页面预加载等
});
// 添加路由返回监听器
routeManager.addPopListener((String route) {
print('从路由返回: $route');
// 执行自定义逻辑,如清理资源、保存状态等
});
// 添加路由替换监听器
routeManager.addReplaceListener((String newRoute, String oldRoute) {
print('路由替换: $oldRoute -> $newRoute');
// 执行自定义逻辑
});
2. 在MaterialApp中注册全局观察者
dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorObservers: [
GlobalRouteObserver(), // 注册全局路由观察者
],
// 其他配置...
);
}
}
3. 动态管理监听器
dart
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
late Function(String) routeListener;
@override
void initState() {
super.initState();
// 创建监听器
routeListener = (String route) {
print('页面 $route 被访问');
};
// 添加监听器
RouteListenerManager.instance.addPushListener(routeListener);
}
@override
void dispose() {
// 移除监听器,避免内存泄漏
RouteListenerManager.instance.removePushListener(routeListener);
super.dispose();
}
}
4. 清理所有监听器
dart
// 在应用退出时清理所有监听器
void cleanup() {
RouteListenerManager.instance.removeAllListener();
}
设计模式
单例模式
-
确保全局只有一个
RouteListenerManager
实例 -
通过私有构造函数和静态实例实现
-
提供工厂构造函数和静态getter两种访问方式
观察者模式
-
RouteListenerManager
作为主题(Subject) -
各种监听器作为观察者(Observer)
-
当路由事件发生时,自动通知所有注册的观察者
策略模式
-
不同类型的路由事件使用不同的处理策略
-
通过函数回调实现灵活的事件处理逻辑
异常处理
所有通知方法都包含异常处理机制:
dart
void notifyPush(String route) {
for (final listener in _pushListeners) {
try {
listener(route);
} catch (e) {
debugPrint('Route push listener error: $e');
}
}
}
-
单个监听器的异常不会影响其他监听器的执行
-
异常信息会通过
debugPrint
输出到控制台 -
确保系统的稳定性和可靠性
注意事项
-
内存管理:及时移除不再需要的监听器,避免内存泄漏
-
异常处理:监听器函数应该处理可能的异常情况
-
性能考虑:避免在监听器中执行耗时操作
-
线程安全:当前实现不是线程安全的,如需多线程访问请添加同步机制
-
路由名称:确保路由有明确的名称,避免使用 'unknown' 作为路由名称
扩展建议
-
添加路由参数传递:支持传递路由参数给监听器
-
添加条件监听:支持基于条件的监听器注册
-
添加优先级机制:支持监听器的优先级排序
-
添加异步支持:支持异步监听器函数
-
添加统计功能:添加路由访问统计和分析功能
总结
RouteListenerManager
提供了一个强大而灵活的路由监听机制,通过单例模式和观察者模式的结合,实现了全局路由事件的统一管理。该设计具有良好的扩展性和维护性,能够满足大多数Flutter应用的路由监听需求。
代码如下,直接拿去,不谢。
typescript
import 'package:flutter/material.dart';
import 'package:get/get.dart';
/// 路由监听管理器
class RouteListenerManager {
static final RouteListenerManager _instance = RouteListenerManager._internal();
factory RouteListenerManager() => _instance;
static RouteListenerManager get instance => _instance;
RouteListenerManager._internal();
final List<Function(String route)> _pushListeners = [];
final List<Function(String route)> _popListeners = [];
final List<Function(String newRoute, String oldRoute)> _replaceListeners = [];
final List<Function(String route)> _removeListeners = [];
/// 添加路由跳转监听器
void addPushListener(Function(String route) listener) {
_pushListeners.add(listener);
}
/// 添加路由返回监听器
void addPopListener(Function(String route) listener) {
_popListeners.add(listener);
}
/// 添加路由替换监听器
void addReplaceListener(Function(String newRoute, String oldRoute) listener) {
_replaceListeners.add(listener);
}
/// 添加路由移除监听器
void addRemoveListener(Function(String route) listener) {
_removeListeners.add(listener);
}
/// 移除路由跳转监听器
void removePushListener(Function(String route) listener) {
_pushListeners.remove(listener);
}
/// 移除路由返回监听器
void removePopListener(Function(String route) listener) {
_popListeners.remove(listener);
}
/// 移除路由替换监听器
void removeReplaceListener(Function(String newRoute, String oldRoute) listener) {
_replaceListeners.remove(listener);
}
/// 移除路由移除监听器
void removeRemoveListener(Function(String route) listener) {
_removeListeners.remove(listener);
}
/// 移除路由全部监听器
void removeAllListener() {
_pushListeners.clear();
_popListeners.clear();
_replaceListeners.clear();
_removeListeners.clear();
}
/// 通知路由跳转
void notifyPush(String route) {
for (final listener in _pushListeners) {
try {
listener(route);
} catch (e) {
debugPrint('Route push listener error: $e');
}
}
}
/// 通知路由返回
void notifyPop(String route) {
for (final listener in _popListeners) {
try {
listener(route);
} catch (e) {
debugPrint('Route pop listener error: $e');
}
}
}
/// 通知路由替换
void notifyReplace(String newRoute, String oldRoute) {
for (final listener in _replaceListeners) {
try {
listener(newRoute, oldRoute);
} catch (e) {
debugPrint('Route replace listener error: $e');
}
}
}
/// 通知路由移除
void notifyRemove(String route) {
for (final listener in _removeListeners) {
try {
listener(route);
} catch (e) {
debugPrint('Route remove listener error: $e');
}
}
}
}
/// 全局路由监听器
class GlobalRouteObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPush(route, previousRoute);
final routeName = route.settings.name ?? 'unknown';
debugPrint('GlobalRouteListener - 路由跳转: $routeName');
RouteListenerManager().notifyPush(routeName);
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
final routeName = route.settings.name ?? 'unknown';
debugPrint('GlobalRouteListener - 路由返回: $routeName');
RouteListenerManager().notifyPop(routeName);
}
@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute != null && oldRoute != null) {
final newRouteName = newRoute.settings.name ?? 'unknown';
final oldRouteName = oldRoute.settings.name ?? 'unknown';
debugPrint('GlobalRouteListener - 路由替换: $oldRouteName -> $newRouteName');
RouteListenerManager().notifyReplace(newRouteName, oldRouteName);
}
}
@override
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didRemove(route, previousRoute);
final routeName = route.settings.name ?? 'unknown';
debugPrint('GlobalRouteListener - 路由移除: $routeName');
RouteListenerManager().notifyRemove(routeName);
}
}