gpt4 book ai didi

flutter - 为什么我必须在 onChanged 中调用 didChange(在 Flutter 中)?

转载 作者:行者123 更新时间:2023-12-04 10:32:58 25 4
gpt4 key购买 nike

我正在尝试在 Form 中使用 DropdownButton 来更新数据库记录,但除非我在 onChanged 中调用 didChange 回调写入数据库的值是 null 而不是从 DropdownMenu 中选择的值。

来自 the documentationdidChange 的目的是触发onChanged,因此必须从INSIDE onChanged 调用它似乎没有任何意义。但如果我不这样做,代码将无法运行。

参见:

import 'package:flutter/material.dart';

void main() => runApp(MinimalReproducibleExample());

class MinimalReproducibleExample extends StatefulWidget {
@override
_MinimalReproducibleExampleState createState() => _MinimalReproducibleExampleState();
}

class _MinimalReproducibleExampleState extends State<MinimalReproducibleExample> {
Enquiry _newEnquiry = Enquiry();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _selectedAgent = '';
String _selectedManager = '';
@override
Widget build(context) {
return MaterialApp(
home: Scaffold(
body: Form(
key: _formKey,
child: Column(
children: [
FormField(
builder: (state) {
return DropdownButton(
items: ['', 'A'].map((val) => DropdownMenuItem<String>(child: Text(val), value: val)).toList(),
value: _selectedAgent,
onChanged: (val) => setState(() {
_selectedAgent = val;
// state.didChange(val);
}),
);
},
onSaved: (val) => _newEnquiry.agent = val,
),
FormField(
builder: (state) {
return DropdownButton(
items: ['', '1'].map((val) => DropdownMenuItem<String>(child: Text(val), value: val)).toList(),
value: _selectedManager,
onChanged: (val) => setState(() {
_selectedManager = val;
state.didChange(val);
}),
);
},
onSaved: (val) => _newEnquiry.manager = val,
),
RaisedButton(
onPressed: () {
_formKey.currentState.save();
print(_newEnquiry.agent);
print(_newEnquiry.manager);
},
),
],
),
),
),
);
}
}

class Enquiry {
String agent;
String manager;
Enquiry({this.agent, this.manager});
}

运行上面的代码(在 Chrome 中,以防设备有所不同)导致:“null 1”被打印出来。但是,当您取消注释注释行时,结果是“A 1”。

为什么有必要?或者我做错了什么?

最佳答案

您可以在下面复制粘贴运行完整代码
原因是 FormField builder 有它自己的 State,在 onSaved 之外只能在调用 state.didChange 后获取值 < br/>有关详细信息,您可以引用 https://medium.com/saugo360/creating-custom-form-fields-in-flutter-85a8f46c2f41Building the CounterFormField 部分

来自文档:其中最重要的是 didChange 方法,只要字段值发生变化,我们就应该使用新值调用该方法。此方法更新字段的值,将更改通知父表单,并重建小部件。

在您的情况下,您可以使用 DropdownButtonFormField 代替

代码片段

DropdownButtonFormField<int>(
value: _ratingController,
items: [1, 2, 3, 4, 5]
.map((label) => DropdownMenuItem(
child: Text(label.toString()),
value: label,
))
.toList(),
hint: Text('Rating'),
onChanged: (value) {
setState(() {
_ratingController = value;
});
},
onSaved: (val) {
print('onSaved drowndownformfield $val');
},
),

工作演示

enter image description here

输出

I/flutter (26553): validating  null
I/flutter (26553): onSaved A null
I/flutter (26553): onSaved 1 1
I/flutter (26553): onSaved drowndownformfield 2
I/flutter (26553): null
I/flutter (26553): 1

完整代码

import 'package:flutter/material.dart';

class MinimalReproducibleExample extends StatefulWidget {
@override
_MinimalReproducibleExampleState createState() =>
_MinimalReproducibleExampleState();
}

class _MinimalReproducibleExampleState
extends State<MinimalReproducibleExample> {
Enquiry _newEnquiry = Enquiry();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _selectedAgent = '';
String _selectedManager = '';
int _ratingController;

@override
Widget build(context) {
return MaterialApp(
home: Scaffold(
body: Form(
key: _formKey,
child: Column(
children: [
FormField(
builder: (state) {
return DropdownButton(
items: ['', 'A']
.map((val) => DropdownMenuItem<String>(
child: Text(val), value: val))
.toList(),
value: _selectedAgent,
onChanged: (val) => setState(() {
_selectedAgent = val;
// state.didChange(val);
}));
},
validator: (val) {
print('validating $val');
return null;
},
onSaved: (val) {
print('onSaved A $val');
_newEnquiry.agent = val;
},
),
FormField(
builder: (state) {
return DropdownButton(
items: ['', '1']
.map((val) => DropdownMenuItem<String>(
child: Text(val), value: val))
.toList(),
value: _selectedManager,
onChanged: (val) => setState(() {
_selectedManager = val;
state.didChange(val);
}),
);
},
onSaved: (val) {
print('onSaved 1 $val');
_newEnquiry.manager = val;
},
),
DropdownButtonFormField<int>(
value: _ratingController,
items: [1, 2, 3, 4, 5]
.map((label) => DropdownMenuItem(
child: Text(label.toString()),
value: label,
))
.toList(),
hint: Text('Rating'),
onChanged: (value) {
setState(() {
_ratingController = value;
});
},
onSaved: (val) {
print('onSaved drowndownformfield $val');
},
),
RaisedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
print(_newEnquiry.agent);
print(_newEnquiry.manager);
}
},
),
],
),
),
),
);
}
}

class Enquiry {
String agent;
String manager;
Enquiry({this.agent, this.manager});
}

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(
title: "test",
),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: MinimalReproducibleExample()),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

关于flutter - 为什么我必须在 onChanged 中调用 didChange(在 Flutter 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60328833/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com