Flutter 使用提供程序重写嵌套的Navigator 2.0示例
我想重写一下。具体地说,我想使用provider编写另一个实现来提升状态,而不是像这里使用ˋhandleBookTappedˋ那样将回调传递到页面 Q:如何使用提供程序将BookAppState传递到页面,同时正确更新外部和内部导航器,而不丢失选项卡的状态。Flutter 使用提供程序重写嵌套的Navigator 2.0示例,flutter,dart,flutter-web,Flutter,Dart,Flutter Web,我想重写一下。具体地说,我想使用provider编写另一个实现来提升状态,而不是像这里使用ˋhandleBookTappedˋ那样将回调传递到页面 Q:如何使用提供程序将BookAppState传递到页面,同时正确更新外部和内部导航器,而不丢失选项卡的状态。 class InnerRouterDelegate extends RouterDelegate<BookRoutePath> with ChangeNotifier, PopNavigatorRouterDelegat
class InnerRouterDelegate extends RouterDelegate<BookRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath> {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
BooksAppState get appState => _appState;
BooksAppState _appState;
set appState(BooksAppState value) {
if (value == _appState) {
return;
}
_appState = value;
notifyListeners();
}
InnerRouterDelegate(this._appState);
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: [
if (appState.selectedIndex == 0) ...[
FadeAnimationPage(
child: BooksListScreen(
books: appState.books,
onTapped: _handleBookTapped,
),
key: ValueKey('BooksListPage'),
),
if (appState.selectedBook != null)
MaterialPage(
key: ValueKey(appState.selectedBook),
child: BookDetailsScreen(book: appState.selectedBook),
),
] else
FadeAnimationPage(
child: SettingsScreen(),
key: ValueKey('SettingsPage'),
),
],
onPopPage: (route, result) {
appState.selectedBook = null;
notifyListeners();
return route.didPop(result);
},
);
}
@override
Future<void> setNewRoutePath(BookRoutePath path) async {
// This is not required for inner router delegate because it does not
// parse route
assert(false);
}
void _handleBookTapped(Book book) {
appState.selectedBook = book;
notifyListeners();
}
}
类InnerRouterDelegate扩展了RouterDelegate
使用ChangeNotifier、PopNavigatorRouterDelegateMixin{
最终GlobalKey navigatorKey=GlobalKey();
BooksAppState获取appState=>\u appState;
BooksAppState appState;
设置appState(BooksAppState值){
如果(值==\u应用状态){
返回;
}
_appState=值;
notifyListeners();
}
InnerRouterDelegate(此应用状态);
@凌驾
小部件构建(构建上下文){
返回导航器(
关键:导航工作,
页码:[
如果(appState.selectedIndex==0)[
FadeAnimationPage(
孩子:书单屏幕(
books:appState.books,
上装:上装把手,
),
key:ValueKey('BooksListPage'),
),
if(appState.selectedBook!=null)
材料页(
key:ValueKey(appState.selectedBook),
子项:BookDetailsScreen(书籍:appState.selectedBook),
),
]否则
FadeAnimationPage(
子项:设置屏幕(),
key:ValueKey('SettingsPage'),
),
],
onPopPage:(路线、结果){
appState.selectedBook=null;
notifyListeners();
返回路线.didPop(结果);
},
);
}
@凌驾
Future setNewRoutePath(BookRoutePath路径)异步{
//内部路由器委托不需要这样做,因为它不需要
//解析路由
断言(假);
}
空的(书本){
appState.selectedBook=book;
notifyListeners();
}
}
MultiProvider
(因为您可能会使用多个)bottomNavigationBar上
replaceappState.
bycontext.watch()。
(注意,我使用enum作为索引,与官方示例略有不同)bottomNavigationBar:
底部导航栏(
类型:BottomNavigationBarType.fixed,
items:BottomNavigationBarItems.items(),
currentIndex:context.watch()。已选择底部Navindex.index,
//currentIndex:appState.selectedBottomNavIndex.index,//替换
onTap:(新索引){
context.read().selectedBottomNavIndex=NavItem.values[newIndex];
//appState.selectedBottomNavIndex=NavItem.values[newIndex];//替换
},
),
这将使它与移动设备一起工作。还有很多web内容也需要更新,代码需要清理/删除
appState
变量已过时。@damian-k-bast您找到如何更新外部和内部委托了吗?我也有同样的问题。
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
/// Providers are above [MyApp] instead of inside it, so that tests
/// can use [MyApp] while mocking the providers
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => MyAppState()),
//ChangeNotifierProvider(create: (_) => Counter()),
],
child: RootRouter(),
),
);
}
@override
Widget build(BuildContext context) {
var idx = context.watch<MyAppState>().selectedBottomNavIndex;
return Navigator(
...
bottomNavigationBar:
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: BottomNavigationBarItems.items(),
currentIndex: context.watch<MyAppState>().selectedBottomNavIndex.index,
//currentIndex: appState.selectedBottomNavIndex.index, //replace
onTap: (newIndex) {
context.read<MyAppState>().selectedBottomNavIndex= NavItem.values[newIndex];
//appState.selectedBottomNavIndex = NavItem.values[newIndex]; //replace
},
),