This commit is contained in:
toly
2023-11-08 09:35:29 +08:00
parent 88cd6fb3b4
commit 8fb4bf57d6
78 changed files with 4344 additions and 544 deletions

View File

@@ -6,17 +6,27 @@ import 'route_history_manager.dart';
import 'routes.dart';
import 'views/not_find_view.dart';
AppRouterDelegate router = AppRouterDelegate();
AppRouterDelegate router = AppRouterDelegate(
initial: IRouteConfig(uri: Uri.parse('/color')),
);
class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
String _path = '/color';
String get path => _path;
/// 核心数据,路由配置数据列表
final List<IRouteConfig> _configs = [];
String get path => current.uri.path;
IRouteConfig get current => _configs.last;
final IRoutePageBuilder? notFindPageBuilder;
AppRouterDelegate({this.notFindPageBuilder}) {
_historyManager.recode(IRouteConfig(uri: Uri.parse(path)));
AppRouterDelegate({
this.notFindPageBuilder,
required IRouteConfig initial,
}) {
_configs.add(initial);
_historyManager.recode(initial);
}
Page _defaultNotFindPageBuilder(_, __) => const MaterialPage(
@@ -45,48 +55,60 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
notifyListeners();
}
// final List<IRouteConfig> _pathStack = [];
bool get canPop => _configs.where((e) => e.routeStyle==RouteStyle.push).isNotEmpty;
final Map<String, Completer<dynamic>> _completerMap = {};
final Map<String, dynamic> _pathExtraMap = {};
final List<String> keepAlivePath = [];
FutureOr<dynamic> changeRoute(IRouteConfig config) {
String value = config.uri.path;
if (_path == value) null;
if (current == config) null;
_handleChangeStyle(config);
if (config.forResult) {
_completerMap[value] = Completer();
}
if (config.keepAlive) {
if (keepAlivePath.contains(value)) {
keepAlivePath.remove(value);
}
keepAlivePath.add(value);
}
if (config.extra != null) {
_pathExtraMap[value] = config.extra;
}
if (config.recordHistory) {
_historyManager.recode(config);
}
_path = value;
notifyListeners();
if (config.forResult) {
return _completerMap[value]!.future;
}
}
void _handleChangeStyle(IRouteConfig config){
switch (config.routeStyle) {
case RouteStyle.push:
if (_configs.contains(config)) {
_configs.remove(config);
}
_configs.add(config);
break;
case RouteStyle.replace:
List<IRouteConfig> liveRoutes = _configs.where((e) => e.keepAlive&&e!=config).toList();
_configs.clear();
_configs.addAll([...liveRoutes,config]);
break;
}
}
FutureOr<dynamic> changePath(
String value, {
bool forResult = false,
Object? extra,
bool keepAlive = false,
bool recordHistory = true,
RouteStyle style = RouteStyle.replace,
}) {
return changeRoute(IRouteConfig(
uri: Uri.parse(value),
forResult: forResult,
extra: extra,
routeStyle: style,
keepAlive: keepAlive,
recordHistory: recordHistory,
));
@@ -96,46 +118,47 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
Widget build(BuildContext context) {
return Navigator(
onPopPage: _onPopPage,
pages: _buildPages(context, path),
pages: _buildPages(context, _configs),
);
}
List<Page> _buildPages(BuildContext context, String path) {
List<Page> _buildPages(BuildContext context, List<IRouteConfig> configs) {
IRouteConfig top = configs.last;
List<IRouteConfig> bottoms = _configs.sublist(0,_configs.length-1).toList();
List<Page> pages = [];
List<Page> topPages = _buildPageByPathFromTree(context, path);
if (keepAlivePath.isNotEmpty) {
for (String alivePath in keepAlivePath) {
if (alivePath != path) {
pages.addAll(_buildPageByPathFromTree(context, alivePath));
}
}
/// 去除和 topPages 中重复的界面
pages.removeWhere(
(element) => topPages.map((e) => e.key).contains(element.key));
}
List<Page> topPages = _buildPageByPathFromTree(context, top);
pages = _buildLivePageByPathList(context, bottoms, top, topPages);
pages.addAll(topPages);
return pages;
}
List<Page> _buildPageByPathFromTree(BuildContext context, String path) {
List<Page> _buildLivePageByPathList(
BuildContext context,
List<IRouteConfig> paths,
IRouteConfig curConfig,
List<Page> curPages,
) {
List<Page> pages = [];
if (paths.isNotEmpty) {
for (IRouteConfig path in paths) {
if (path != curConfig) {
pages.addAll(_buildPageByPathFromTree(context, path));
}
}
/// 去除和 curPages 中重复的界面
pages.removeWhere((page) => curPages.map((e) => e.key).contains(page.key));
}
return pages;
}
List<Page> _buildPageByPathFromTree(
BuildContext context, IRouteConfig config) {
List<Page> result = [];
List<IRouteNode> iRoutes = rootRoute.find(path);
List<IRouteNode> iRoutes = rootRoute.find(config.path);
if (iRoutes.isNotEmpty) {
for (int i = 0; i < iRoutes.length; i++) {
IRouteNode iroute = iRoutes[i];
String path = iroute.path;
Object? extra = _pathExtraMap[path];
bool keepAlive = keepAlivePath.contains(path);
bool forResult = _completerMap.containsKey(path);
IRouteConfig config = IRouteConfig(
uri: Uri.parse(path),
extra: extra,
keepAlive: keepAlive,
forResult: forResult,
);
config = config.copyWith(path: iroute.path);
Page? page;
if (iroute is NotFindNode) {
page = (notFindPageBuilder ?? _defaultNotFindPageBuilder)(context, config);
@@ -145,6 +168,9 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
if (page != null) {
result.add(page);
}
if(iroute is CellIRoute){
break;
}
}
}
return result;
@@ -156,12 +182,29 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
return true;
}
void backStack() {
if (_configs.isNotEmpty) {
_configs.removeLast();
if (_configs.isNotEmpty) {
changeRoute(_configs.last);
} else {
changeRoute(current);
}
}
}
bool _onPopPage(Route route, result) {
if (_completerMap.containsKey(path)) {
_completerMap[path]?.complete(result);
_completerMap.remove(path);
}
changePath(backPath(path), recordHistory: false);
if (_configs.isNotEmpty) {
_configs.removeLast();
notifyListeners();
} else {
changePath(backPath(path), recordHistory: false);
}
return route.didPop(result);
}