flutter - Flutter:使用ChangeNotifier更新TextFormField文本

标签 flutter dart provider changenotifier

在一个复杂的场景中,当Model扩展TextFormField发送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);
      })
    ]));
  }
}

最佳答案

您运行的第二个示例在运行时没有任何错误:

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 _text2Ctl = TextEditingController();

  @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'),
      ),

      // 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);
      })
    ]));
  }
}
Demo

关于flutter - Flutter:使用ChangeNotifier更新TextFormField文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64098695/

相关文章:

android - GPS 提供商已启用但 getLastKnownLocation(provider) 返回 null

javascript - @Injectable 服务中的 HTTP 提供程序

dart - 对齐警报对话框按钮栏小部件

authentication - 在安全或自定义提供程序之前加载监听器

flutter - Flutter中如何设置PageView的初始页面?

flutter - 通过 MaterialPageRoute 导航

pdf - 我想从PDF文件中获取总页数

android - flutter_ffmpeg - 如何访问输出路径?

dart - 在类名前面添加下划线是确保类在库外部不可用的正确方法吗?

flutter - 更改 'inheritFromWidgetOfExactType' 后,我开始收到 3 个不同的新错误