如何使用 StreamBuilder 更新 TextField 的值?
Posted
技术标签:
【中文标题】如何使用 StreamBuilder 更新 TextField 的值?【英文标题】:How to update value for TextField using StreamBuilder? 【发布时间】:2020-04-21 01:22:59 【问题描述】:我有一个textfield
,我在我的应用程序中使用sqflite
数据库。 sqflite
有一个值,我需要分配给我的textfield
这是我的textfield
代码
StreamBuilder<String>(
stream: patientHealthFormBloc.doctorName,
builder: (context, snapshot)
return TextFormField(
initialValue: patientHealthFormBloc.doctorNameValue,
onChanged: (value)
patientHealthFormBloc.doctorNameChanged(value);
,
...
现在在我班级的initstate
方法中,我正在从数据库中获取值。
这是一个异步操作,所以需要时间。
我的 bloc 类有如下代码
Function(String) get doctorNameChanged => _doctorName.sink.add;
所以一旦我从数据库中收到值,我就会调用以下内容
doctorNameChanged("valuefromdatabase");
但我看不到我的文本字段中的值。我的数据库中也存在一个值。
是否可以在不使用TextEditingController
或setState
的情况下更新值。我想避免这些,因为我的班级被分成很多块,而且太复杂而无法使用上述任何一种
我尝试对RadioButton
和CheckBox
使用相同的方法,它们似乎可以正确更新。
该值也在数据库中存在的_doctorName.stream.value
中更新,但textfield
不显示任何数据。我还尝试更改textfield
的颜色,所以那里没有问题,而且我可以看到我输入的内容。
我已经做了一个应用程序的小演示https://github.com/PritishSawant/demo/tree/master/lib
我没有使用sqflite
,而是使用shared preferences
,但问题仍然存在
【问题讨论】:
尝试删除“initialValue: patientHealthFormBloc.doctorNameValue”,并在 StreamBuilder 的“initialData”中启动它 @Stel 谢谢,但不起作用 你可以使用 TextEditingController(text: ) @ChinkySight 我正在使用 Stream 来避免 TextEditingController。应用复杂,使用TextEditingController不可行 在您的示例中,您根本没有使用快照。您希望从中提取哪些数据以在您的 TextFormField 中使用?为什么不能使用 TextEditingController? 【参考方案1】:尝试以下方法:
StreamBuilder<String>(
stream: patientHealthFormBloc.doctorName,
builder: (context, snapshot)
String doctorName = patientHealthFormBloc.doctorNameValue;
if(snapshot.hasData)
doctorName = snapshot.data/*(your name string from the stream)*/;
return TextFormField(
initialValue: doctorName,
onChanged: (value)
patientHealthFormBloc.doctorNameChanged(value);
,
...
【讨论】:
你收到新名字了吗? 您是否在builder: (context, snapshot)
中收到相同的新名称?
当我输入文本时,我会收到输入的文本。在我从 db 获取的初始阶段,它正在打印 db 值。StreamBuilder 工作正常,当我手动输入时值会更新,但从数据库中获取时它不会更新
为了从数据库中获取刷新的数据,您需要在流构建器中使用返回数据库结果的方法进行更改
@Stel 但它适用于单选按钮和复选框,为什么不适用于文本字段。不需要另一个用于数据库的流构建器,因为我已经为文本字段添加了一个流构建器,并在我从 db 获取数据时更改它的值【参考方案2】:
我的 cmets 中的建议是这样的:
TextEditingController _textEditingController = TextEditingController();
@override
void initState()
patientHealthFormBloc.doctorName.listen((snapshot)
setState(()
_textEditingController.text = snapshot;
);
);
super.initState();
@override
Widget build(BuildContext context)
return Scaffold(
body: Column(
children: <Widget>[
TextFormField(
controller: _textEditingController,
onChanged: (value)
patientHealthFormBloc.doctorNameChanged(value);
,
],
),
);
我不想在不理解您为什么不想使用 TextEditingController 或 setState 的情况下写下这个答案。但这应该可以在使用 Bloc 模式时达到您想要的效果。
【讨论】:
一开始我有这个想法,但由于引用的问题和@Nudge坚持不使用TextEditController
,所以我刮掉了这个想法。很棒的是,只有使用控制器,解决方案才能变得简单而小巧,以便准确地工作。干得好。
谢谢,我很感激。不幸的是,用户似乎坚持自己的想法,而不是尝试编写适当的解决方案,因此他们决定不归因于正确的响应或赏金。【参考方案3】:
好的,所以我终于找到了解决问题的方法。
以下是我的代码,我刚刚在下面的示例中使用了SharedPreferences
而不是sqflite
。sqflite
也可以做同样的事情
class _MyHomePageState extends State<MyHomePage>
MyBloc myBloc = MyBloc();
TextEditingController myController = TextEditingController();
@override
void dispose()
myBloc?.close();
myController?.dispose();
super.dispose();
@override
void initState()
super.initState();
AppPreferences.setString("data", "this is my data");
AppPreferences.getString("data").then((value)
myBloc.dataChanged(value);
);
@override
Widget build(BuildContext context)
return Scaffold(
body: Center(
child: StreamBuilder(
stream: myBloc.data,
builder: (context,snapshot)
debugPrint(snapshot.data);
myController.value = myController.value.copyWith(text: myBloc.dataValue);
return TextFormField(
controller: myController,
onChanged: (value)
myBloc.dataChanged(value);
,
);
,
),
),
);
【讨论】:
这是一个设计过度的解决方案。我希望您已经解释了您最初想要实现的目标,而不是希望我们解决您的特定解决方案。正如我对您的问题所评论的那样,您似乎想要对用户可能正在积极使用的 TextField 进行实时更新。这是非常奇怪的,可能是糟糕的用户体验。 @JoãoSoares 你能发布你的解决方案吗?如果您的解决方案比我的好,我很高兴奖励赏金并接受您的解决方案。我刚刚发布了一个更简单的解决方案,以便每个人都能理解,但实际上我的应用程序需要与 sqflite 以及 firestore 同步,因此它可能看起来对您来说设计过度 如果您能解释为什么要在用户可能正在使用 TextFieldForm 的同时流式传输(更新)它的值,我可能会为您提供帮助。与 SQFlite 和 Firestore 同步与我声称您提供的解决方案过度设计无关。 我已经多次阅读了这个问题,并且看到了您在 GitHub 上分享的代码。您的解释说明了您想要做什么以及您希望如何编写代码。它没有解释为什么要让 TextFormField 以这种方式填充数据流或该行为的前提。 根据您的解释,我的理解是您希望 TextFormField 流式传输数据库中的当前值。然后您期望当用户保存表单并更新数据库时,您的 TextFormField 中的值会从数据库中更新。即使它已经更新,因为您刚刚输入了新值。以上是关于如何使用 StreamBuilder 更新 TextField 的值?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 StreamBuilder 中更新 Flutter Cards 而无需重置状态?
如何更新 Storage 中的图片并刷新 Streambuilder 以显示新图片?
Flutter:从子 StreamBuilder 更新有状态小部件