use*_*629 0 android flutter flutter-provider
我想要一个“设置”屏幕,我可以在其中选择要返回到第一个屏幕的颜色。
当“设置”屏幕关闭时,我无法更新第一个屏幕。
我使用提供程序作为更改通知程序。但我看不到如何触发第一个屏幕的更新。第三个按钮创建一个更新屏幕的事件,但这可以自动完成吗?
我错过了什么...?
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
Color bgColor = Colors.yellow[100];
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: MyHomeScreen());
}
}
class MyHomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => ColorModel()),
],
child: Consumer<ColorModel>(builder: (context, colorModel, child) {
return Scaffold(
appBar: AppBar(title: Text('Thanks for your help :)')),
body: Container(
constraints: BoxConstraints.expand(),
color: bgColor,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Change background color on this screen'),
OutlinedButton(
style: OutlinedButton.styleFrom(
backgroundColor: Colors.green[600],
),
child:
Text('Button1', style: TextStyle(color: Colors.white)),
onPressed: () {
var result = Navigator.push(
context, MaterialPageRoute(builder: (context) => Screen2()));
print('>>> Button1-onPressed completed, result=$result');
},
),
OutlinedButton(
style: OutlinedButton.styleFrom(
backgroundColor: Colors.green[600],
),
child:
Text('Choose a colour', style: TextStyle(color: Colors.white)),
onPressed: () {
asyncButton(context);
print('>>> Screen1 Button-onPressed completed');
},
),
OutlinedButton(
style: OutlinedButton.styleFrom(
backgroundColor: Colors.green[600],
),
child:
Text('Now try me', style: TextStyle(color: Colors.white)),
onPressed: () {
colorModel.notifyListeners();
},
),
],
),
),
);
}),
);
}
void asyncButton(BuildContext context) async {
var result = await Navigator.push(
context, MaterialPageRoute(builder: (context) => Screen2()));
print('>>> asyncButton completed: result = $result');
bgColor = result;
}
}
class ColorModel with ChangeNotifier {
void updateDisplay() {
notifyListeners();
}
}
class Screen2 extends StatelessWidget {
int _value;
List<String> names = ['Red', 'Green', 'Blue'];
List<Color> colors = [Colors.red[100], Colors.green[100], Colors.blue[100]];
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => ColorModel()),
],
child: Scaffold(
appBar: AppBar(
toolbarHeight: 80,
backgroundColor: Colors.blue,
title: Center(child: Text('Screen2')),
),
body: Container(
constraints: BoxConstraints.expand(),
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Consumer<ColorModel>(builder: (context, colorModel, child) {
return DropdownButton(
value: _value,
hint: Text("Select a color"),
focusColor: Colors.lightBlue,
onChanged: (int value) {
Navigator.pop(context, colors[value]);
},
items: [
DropdownMenuItem(value: 0, child: Text(names[0])),
DropdownMenuItem(value: 1, child: Text(names[1])),
DropdownMenuItem(value: 2, child: Text(names[2])),
],
);
}),
],
),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
Navigator.push与 一起使用很棘手Provider。它会导致很多"Could not find the correct Provider above this Navigator Widget"错误。我已经在相关问题的回答中解释了原因。
以下是您情况的快速概述:
\n问题代码中的架构:
\nMaterialApp\n > provider(Screen A)\n > provider(Screen B)\nRun Code Online (Sandbox Code Playgroud)\n解决方案中的架构如下:
\nprovider(MaterialApp)\n > Screen A\n > Screen B\nRun Code Online (Sandbox Code Playgroud)\n这是您的代码示例,已缩短,使用Provider,从第 2 页更新第 1 页的背景颜色。
我在整个代码中添加了注释来解释更改。
\nimport \'package:flutter/material.dart\';\nimport \'package:provider/provider.dart\';\n\n// - global var removed -\n// Color bgColor = Colors.yellow[100];\n\nvoid main() {\n runApp(ProviderApp());\n}\n\nclass ProviderApp extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n /// Define your Provider here, above MaterialApp\n return ChangeNotifierProvider(\n create: (context) => ColorModel(),\n child: MaterialApp(\n title: \'Flutter Demo\',\n debugShowCheckedModeBanner: false,\n home: ScreenA()\n ),\n );\n }\n}\n\nclass ScreenA extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Scaffold(\n appBar: AppBar(title: Text(\'Thanks for your help :)\')),\n body: Container(\n constraints: BoxConstraints.expand(),\n //\n // color: bgColor // - global var removed -\n color: Provider.of<ColorModel>(context).bgColor,\n // \xe2\x86\x91 use your Provider state-stored value here \xe2\x86\x91\n //\n child: Column(\n mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n children: [\n Text(\'Change background color on this screen\'),\n OutlinedButton(\n style: OutlinedButton.styleFrom(\n backgroundColor: Colors.green[600],\n ),\n child: Text(\'Go Screen B\', style: TextStyle(color: Colors.white)),\n // Navigator.push returns a Future, must async/await to use return value\n onPressed: () async {\n var result = await Navigator.of(context).push(\n MaterialPageRoute(builder: (context) => ScreenB()));\n // note that this context is not Screen A context, but MaterialApp context\n // see /sf/answers/4654012541/\n print(\'>>> Button1-onPressed completed, result=$result\');\n },\n ),\n ],\n ),\n ),\n );\n }\n}\n\n/// This is your state object. Store your state here.\n/// Create this once and use anywhere you need. Don\'t re-create this unless\n/// you want to wipe out all state data you were holding/sharing.\nclass ColorModel with ChangeNotifier {\n // color is the state info you want to store & share\n Color bgColor = Colors.yellow[100]; // initialized to yellow\n\n /// Update your state value and notify any interested listeners\n void updateBgColor(Color newColor) {\n bgColor = newColor;\n notifyListeners();\n }\n\n /// - removed - replaced with updateBgColor \xe2\x86\x91\n /*void updateDisplay() {\n notifyListeners();\n }*/\n}\n\nclass ScreenB extends StatelessWidget {\n // all fields in StatelessWidgets should be final\n //final int value; // this value isn\'t needed\n final List<String> names = [\'Red\', \'Green\', \'Blue\'];\n final List<Color> colors = [Colors.red[100], Colors.green[100], Colors.blue[100]];\n\n @override\n Widget build(BuildContext context) {\n /// Instantiating your model & giving it to Provider to should only happen once per\n /// Widget Tree that needs access to that state. e.g. MaterialApp for this solution\n /// The state object & Provider below was repeated & has been commented out / removed.\n /// This was wiping out any previously stored state and creating a new Provider / Inherited scope\n /// to all children.\n /*return MultiProvider(\n providers: [\n ChangeNotifierProvider(create: (context) => ColorModel()),\n ],\n child: ,\n );*/\n // - end of duplicate Provider removal -\n return Scaffold(\n appBar: AppBar(\n title: Text(\'Screen2\'),\n ),\n body: Container(\n alignment: Alignment.center,\n child: Consumer<ColorModel>(builder: (context, colorModel, child) {\n return DropdownButton(\n //value: value, // this value isn\'t needed\n hint: Text("Select a color"),\n onChanged: (int value) {\n colorModel.updateBgColor(colors[value]);\n Navigator.pop(context, colors[value]);\n },\n items: [\n DropdownMenuItem(value: 0, child: Text(names[0])),\n DropdownMenuItem(value: 1, child: Text(names[1])),\n DropdownMenuItem(value: 2, child: Text(names[2])),\n ],\n );\n }),\n ),\n );\n }\n}\n\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2823 次 |
| 最近记录: |