flutter - 继承的小部件和导航器
问题描述
我找到了一些关于这个的答案 [ here , here ],但没有一个能完全回答我的问题。
我将使用包提供程序来描述我的问题,因为它大大减少了样板代码。
我想要做的是在(且仅在)调用路由时注入依赖项。我可以通过做这样的事情来实现这一点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 上一次注入所有依赖项,我想在需要时注入它们。
每次我需要另一个“折叠”时,我都考虑过创建新的导航器,但这似乎很快就变得非常混乱。
我该如何解决这个问题?
解决方案
在以下示例中,路由/
和/login
都可以访问Provider.of<int>
,但路由/other
不能。
有两种解决方案:
- A
StatefulWidget
与Provider.value
包裹每条路线的 a 相结合。
例子:
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(),
},
),
);
}
推荐阅读
- memory-leaks - 当我重新启动我的电脑时,堆内存会被释放吗?
- django - 扩展组模型的嵌套序列化程序在用户序列化程序中缺少某些字段
- javascript - 停止在三个 JS 中长距离加载对象
- python - 根据某些条件从字典的python字典中删除键
- linux - 两个列表之间的 grep
- python - Django 模板中的日期和时间
- javascript - 地图条目存储在哪里?
- powershell - 如何将字符串连接到powershell中嵌套数组内的值?
- javascript - 我想使用 next.js 中的 getInitialProps() 记录我的数据
- ms-word - 如何使标题 4 向下:Markdown to Word