flutter - 使用继承的小部件将数据传递到多个屏幕
问题描述
有一些InheritedWidget
我不明白的困惑。
我已经搜索并阅读了一些关于 stackoverflow 的 QA InheritedWidget
,但仍有一些我不明白的地方。
首先,让我们创建一个场景。
这是我的InheritedWidget
:
class MyInheritedWidget extends InheritedWidget {
final String name;
MyInheritedWidget({
@required this.name,
@required Widget child,
Key key,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) =>
oldWidget.name != this.name;
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
}
这就是MyHomePage
包含MyInheritedWidget
. MyInheritedWidget
有两个孩子:WidgetA
和一个导航到另一个屏幕的按钮,在这种情况下Page1
。
class MyHomePage extends StatefulWidget {
@override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: MyInheritedWidget(
name: 'Name',
child: Column(
children: [
WidgetA(),
TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Page1(),
),
);
},
child: Text('Go to page 1'),
)
],
),
),
),
);
}
}
里面WidgetA
有一个文本小部件,显示来自的名称字段MyInheritedWidget
和导航到的另一个按钮Page2
。
class WidgetA extends StatefulWidget {
@override
_WidgetAState createState() => _WidgetAState();
}
class _WidgetAState extends State<WidgetA> {
@override
Widget build(BuildContext context) {
final myInheritedWidget = MyInheritedWidget.of(context);
return Column(
children: [
Text(myInheritedWidget.name),
TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Page2(),
),
);
},
child: Text('Go to page 2'),
)
],
);
}
}
Page1
每个都只有一个文本小部件,Page2
显示来自.MyInheritedWidget
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final myInheritedWidget = MyInheritedWidget.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Page 1'),
),
body: Text(myInheritedWidget.name),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final myInheritedWidget = MyInheritedWidget.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Page 2'),
),
body: Text(myInheritedWidget.name),
);
}
}
在这种情况下,name字段MyInheritedWidget
是不可访问的 formPage1
和Page2
,但可以在 中访问WidgetA
。
现在让我们来看看这个问题:
据说InheritedWidget
可以从它的所有后代访问。子孙是什么意思?
在MyHomePage
,我知道WidgetA
是一个后裔MyInheritedWidget
。但是,Page1
也是?的后裔MyInheritedWidget
?
如果答案是否定的,我怎样才能成为Page1
的后代MyInheritedWidget
?
我需要再把它包在里面MyInheritedWidget
吗?
如果有这样的导航链怎么办:Page1 -> Page2 -> Page3 ... Page10并且我想MyInheritedWidget
在Page10中访问,我必须将每个页面都包装在里面MyInheritedWidget
吗?
解决方案
正如@pskink 所说,MyHomePage
pushesPage1
是 的后代Navigator
,它是 under MaterialApp
, not MyInheritedWidget
。最简单的解决方案是在MyInheritedWidget
上面创建MaterialApp
. 这是我的代码(使用ChangeNotifierProvider
代替MyInheritedWidget
)。
void main() {
setupLocator();
runApp(DevConnectorApp());
}
class DevConnectorApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final log = getLogger('DevConnectorApp');
return MultiProvider(
providers: [
ChangeNotifierProvider<AuthService>(
create: (ctx) => AuthService(),
),
ChangeNotifierProxyProvider<AuthService, ProfileService>(
create: (ctx) => ProfileService(),
update: (ctx, authService, profileService) =>
profileService..updateAuth(authService),
),
],
child: Consumer<AuthService>(builder: (ctx, authService, _) {
log.v('building MaterialApp with isAuth=${authService.isAuth}');
return MaterialApp(
这是一个使用 multipleNavigators
来确定InheritedWidget
. 该小部件为您的示例中的屏幕ContextWidget
创建一个InheritedWidget
和一个Navigator
并具有子小部件。
class InheritedWidgetTest extends StatefulWidget {
@override
State createState() => new InheritedWidgetTestState();
}
class InheritedWidgetTestState extends State<InheritedWidgetTest> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: Column(
children: [
ContextWidget('First'),
ContextWidget('Second'),
],
),
),
);
}
}
class ContextWidget extends StatelessWidget {
Navigator _getNavigator(BuildContext context, Widget child) {
return new Navigator(
onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute(builder: (context) {
return child;
});
},
);
}
final name;
ContextWidget(this.name);
@override
Widget build(BuildContext context) {
return MyInheritedWidget(
name: this.name,
child: Expanded(
child: _getNavigator(
context,
PageWidget(),
),
),
);
}
}
class PageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
WidgetA(),
TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Page1(),
),
);
},
child: Text('Go to page 1'),
)
],
);
}
}
推荐阅读
- postgresql - 是否可以在靶心中安装 postgresql-dev
- javascript - Javascript倒数计时器在两个计时器之间洗牌
- android - OnLocationChanged() 在后台不起作用
- python - 如何在 Python 中通过 Hortonworks Sandbox 运行 MapReduce 脚本?
- go - 执行是否必须不断停止才能设置断点?
- php - 如何使用 POST 将数据流式传输到 PHP 脚本
- oracle - SSIS Oracle 连接管理器
- javascript - 如何使用带有完整文档字符串的 iframe 标记
- c# - JAMS.dll 无法解析类型引用 [Acumatica] 2020 R1
- sql - from_number 多久调用一次 to_number?