我不确定我从上面的代码片段中是否完全理解你在做什么,但我想我理解这个要求:
- Menu1 有状态
- SubMenu1 应该能够读取和更新 Menu1 状态
- Menu1 调用 SubMenu1 作为“子”屏幕,没有其他路径到 SubMenu1
处理这种简单状态的最简单方法是让 Menu1 在显示时将其状态传递给 SubMenu1(作为构造函数参数),并让 SubMenu1 直接更新它。我在下面显示了示例代码。当然,这是两个屏幕之间的紧耦合,但它似乎是一个紧耦合的要求。
Provider 包可用于将状态与 UI 分开。您可以使用这种方法。你说“但是突然之间,我的表单不再在每次调用 Menu1 时都被初始化,而是在应用程序启动时才初始化一次”。 Menu1 可以在调用时调用一个方法来初始化 Provider 吗?我为 Provider 方法添加了示例代码。一些简短的说明:
- 我使用 MultiProvider,尽管我只有一个 ChangeNotifierProvider,但这会让您的代码更易于阅读
- ChangeNotifier FormData 保存表单状态
- 父窗体初始化窗体状态
- 两种表单都调用 FormData 方法来设置和获取状态
长示例代码直接状态如下:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: FormTest(),
),
),
);
}
}
class FormTest extends StatefulWidget {
@override
_FormTestState createState() => _FormTestState();
}
class _FormTestState extends State<FormTest> {
int _selectedIndex = 0;
final List<Widget> _options = [
FormWidget(),
PlaceholderWidget(Colors.deepOrange),
PlaceholderWidget(Colors.green)
];
void _onItemTap(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Example'),
backgroundColor: Colors.teal),
body: Center(
child: _options.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.teal),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
backgroundColor: Colors.cyan),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
backgroundColor: Colors.lightBlue,
),
],
type: BottomNavigationBarType.shifting,
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.grey,
iconSize: 40,
onTap: _onItemTap,
elevation: 5),
);
}
}
class PlaceholderWidget extends StatelessWidget {
final Color color;
PlaceholderWidget(this.color);
@override
Widget build(BuildContext context) {
return Container(
color: color,
);
}
}
class FormWidget extends StatefulWidget {
@override
FormWidgetState createState() {
return FormWidgetState();
}
}
class FormWidgetState extends State<FormWidget> {
final _formKey = GlobalKey<FormState>();
final _formData = {};
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
onSaved: (value) {
_formData['parent'] = value;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Parent text: ' + _formData['parent'])));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SubFormWidget(_formData)),
);
}
},
child: Text('SubForm'),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Subform text: ' + _formData['child'])));
}
},
child: Text('Submit'),
),
),
],
),
);
}
}
class SubFormWidget extends StatefulWidget {
final Map _formData;
SubFormWidget(this._formData);
@override
SubFormWidgetState createState() {
return SubFormWidgetState();
}
}
class SubFormWidgetState extends State<SubFormWidget> {
final _subFormKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _subFormKey,
child: Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Example'),
backgroundColor: Colors.teal),
body: Column(
children: <Widget>[
Text(widget._formData['parent']),
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
onSaved: (value) {
widget._formData['child'] = value;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_subFormKey.currentState!.validate()) {
_subFormKey.currentState!.save();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Subform text: ' + widget._formData['child'])));
Navigator.pop(context);
}
},
child: Text('Submit'),
),
),
],
),
),
);
}
}
Provider 方法的长示例代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<FormData>(
create: (ctx) => FormData(),
),
],
child: MaterialApp(
title: 'Test App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FormTest2(),
),
);
}
}
class FormTest2 extends StatefulWidget {
FormTest2({Key key}) : super(key: key);
@override
_FormTest2State createState() => _FormTest2State();
}
class _FormTest2State extends State<FormTest2> {
int _selectedIndex = 0;
final List<Widget> _options = [
FormWidget2(),
PlaceholderWidget(Colors.deepOrange),
PlaceholderWidget(Colors.green)
];
void _onItemTap(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Example 2'),
backgroundColor: Colors.teal),
body: Center(
child: _options.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.teal),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
backgroundColor: Colors.cyan),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
backgroundColor: Colors.lightBlue,
),
],
type: BottomNavigationBarType.shifting,
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.grey,
iconSize: 40,
onTap: _onItemTap,
elevation: 5),
);
}
}
class PlaceholderWidget extends StatelessWidget {
final Color color;
PlaceholderWidget(this.color);
@override
Widget build(BuildContext context) {
return Container(
color: color,
);
}
}
class FormWidget2 extends StatefulWidget {
@override
FormWidget2State createState() {
return FormWidget2State();
}
}
class FormData extends ChangeNotifier {
var _formData = <String, String>{};
void init() {
_formData = <String, String>{};
// No notifyListeners() needed in this use case
}
void setEntry(String key, String value) {
_formData[key] = value;
// notifyListeners() may or may not be needed in this use case
notifyListeners();
}
String getEntry(String key) {
var value = _formData[key];
return value;
}
}
class FormWidget2State extends State<FormWidget2> {
final _formKey = GlobalKey<FormState>();
@override
void initState() {
Provider.of<FormData>(context, listen: false).init();
super.initState();
}
@override
Widget build(BuildContext context) {
return Consumer<FormData>(
builder: (context, formData, _) => Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
initialValue: formData.getEntry('parent'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
onSaved: (value) {
formData.setEntry('parent', value);
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Parent text: ' + formData.getEntry('parent'))));
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SubFormWidget2()),
);
}
},
child: Text('SubForm'),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Subform text: ' + formData.getEntry('child'))));
}
},
child: Text('Submit'),
),
),
],
),
),
);
}
}
class SubFormWidget2 extends StatefulWidget {
@override
SubFormWidget2State createState() {
return SubFormWidget2State();
}
}
class SubFormWidget2State extends State<SubFormWidget2> {
final _subFormKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _subFormKey,
child: Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Example 2'),
backgroundColor: Colors.teal),
body: Consumer<FormData>(
builder: (context, formData, _) => Column(
children: <Widget>[
Text(formData.getEntry('parent')),
TextFormField(
initialValue: formData.getEntry('child'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
onSaved: (value) {
formData.setEntry('child', value);
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_subFormKey.currentState.validate()) {
_subFormKey.currentState.save();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Subform text: ' + formData.getEntry('child'))));
Navigator.pop(context);
}
},
child: Text('Submit'),
),
),
],
),
),
),
);
}
}