在一个复杂的场景中,当 a由扩展的模型发送时,我需要更新一些TextFormField
s的文本。问题是要更改 a 的文本,您必须使用暗示重建的 setter,因此您不能将其用于方法中。但是要访问模型,您需要方法内部的。notifyListeners()
ChangeNotifier
TextFormField
TextFormField.text
build
Provider
context
build
MWE(很明显按钮在实际项目中的另一个Widget中,还有更多TextFormField
)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyModel extends ChangeNotifier {
void updateCounter() {
++_counter;
notifyListeners();
}
MyModel() {
_counter = 1;
}
int _counter;
String get counter => _counter.toString();
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => MyModel(),
child: MaterialApp(
title: 'Test',
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _text1Ctl = TextEditingController();
var _text2Ctl = TextEditingController();
@override
void initState() {
super.initState();
final model = MyModel();
model.addListener(() {
_text1Ctl.text = model.counter;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
FlatButton(
onPressed: () {
Provider.of<MyModel>(context, listen: false).updateCounter();
},
child: Text('Press me'),
),
// 1st attempt
// Doesn't work because the listener isn't applied to the instance of the model provided by the provider.
TextFormField(controller: _text1Ctl),
// 2nd attempt
// Works but with `Another exception was thrown: setState() or markNeedsBuild() called during build.` because it changes text via controller (which implies a rebuild) during building.
Consumer<MyModel>(builder: (context, model, child) {
_text2Ctl.text = model.counter;
return TextFormField(controller: _text2Ctl);
})
]));
}
}