我找到了有关此[here,here]的一些答案,但没有一个答案能完全回答我的问题。
我将使用软件包provider来描述我的问题,因为它大大减少了样板代码。
我想做的是在(且仅)在调用路由时注入依赖项。我可以通过在onGenerateRoute
上做类似的事情来实现:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Routes Demo',
initialRoute: '/',
onGenerateRoute: (settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => HomePage());
case '/firstPage':
return MaterialPageRoute(
builder: (_) => Provider(
builder: (_) => MyComplexClass(),
child: FirstPage(),
),
);
case '/secondPage':
return MaterialPageRoute(builder: (_) => SecondPage());
default:
return MaterialPageRoute(
builder: (_) => Scaffold(
body: Center(
child: Text('Route does not exists'),
),
),
);
}
});
}
}
class MyComplexClass {
String message = 'UUUH I am so complex';
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RaisedButton(
child: Text('Go to first page'),
onPressed: () {
Navigator.pushNamed(context, '/firstPage');
}),
],
),
));
}
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final myComplexClass = Provider.of<MyComplexClass>(context);
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Center(
child: Text(myComplexClass.message),
),
RaisedButton(
child: Text('Go to second page'),
onPressed: () {
Navigator.pushNamed(context, '/secondPage');
},
)
],
),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final myComplexClass = Provider.of<MyComplexClass>(context);
return Scaffold(
body: Center(
child: Text(myComplexClass.message),
),
);
}
}
这对于'/ firstPage'来说很好用,但是一旦我从'firstPage'内部推送另一条路由,上下文就会丢失,并且由于导航器停留在树的顶部,因此我无法访问MyComplexClass
与MaterialApp一起使用时,下一条路线将松散注入MyComplexClass的上下文,我无法设法找到一种完美的解决方案。
我们可以看到SecondPage
不是Provider
的子级,因此是问题。
我不想将所有具有的依赖项一次性注入MainApp之上,我想根据需要注入它们。
我考虑过每当我需要另一个“折叠”时创建新的导航器,但这似乎很快变得非常混乱。
我该如何解决这个问题?
答案 0 :(得分:1)
在以下示例中,路由/
和/login
都可以访问Provider.of<int>
,而路由/other
无法访问。
有两种解决方案:
StatefulWidget
与一个Provider.value
组合在一起,用于包装每条路线。示例:
class Foo extends StatefulWidget {
@override
_FooState createState() => _FooState();
}
class _FooState extends State<Foo> {
int myState = 42;
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (_) => Provider.value(value: myState, child: Home()),
'/login': (_) => Provider.value(value: myState, child: Login()),
'/other': (_) => Other(),
},
);
}
}
MaterialApp
与ProxyProvider
组合在一起的私有占位符类型:示例:
class _Scope<T> {
_Scope(this.value);
final T value;
}
// ...
Widget build(BuildContext context) {
Provider(
builder: (_) => _Scope(42),
child: MaterialApp(
routes: {
'/': (_) => ProxyProvider<_Scope<int>, int>(
builder: (_, scope, __) => scope.value, child: Home()),
'/login': (_) => ProxyProvider<_Scope<int>, int>(
builder: (_, scope, __) => scope.value, child: Login()),
'/other': (_) => Other(),
},
),
);
}