[英]Flutter not showing BLoC stream value on TextField widget
I am trying to make a screen where the user can add a person's birthday in one moment, but in another moment the same screen should load the data from Firebase and display in the TextFields
the value loaded.我正在尝试制作一个屏幕,用户可以在某个时刻添加一个人的生日,但在另一个时刻,同一屏幕应该从 Firebase 加载数据并在
TextFields
显示加载的值。 I am using BLoC
with stream to perform this.我正在使用带有流的
BLoC
来执行此操作。 I can load the data from Firebase correctly and pass it to the screen with StreamBuilders
in each TextField
, but the values are not showing, even though the streams contains the correct value.我可以从 Firebase 正确加载数据,并在每个
TextField
使用StreamBuilders
将其传递到屏幕,但即使流包含正确的值,也没有显示值。 In the same page I use some DropdownButtons
for selectable data and they receive and show the value just fine.在同一页面中,我将一些
DropdownButtons
用于可选数据,它们接收并显示值就好了。 I'm not sure what am I doing wrong.我不确定我做错了什么。
This is the code for each TextField
:这是每个
TextField
的代码:
class InputField extends StatelessWidget {
final IconData icon;
final String hint;
final bool obscure;
final TextInputType type;
final Stream<String> stream;
final Function(String) onChanged;
InputField({this.icon, this.hint, this.obscure, this.type, this.stream, this.onChanged});
@override
Widget build(BuildContext context) {
return StreamBuilder<String>(
stream: stream,
builder: (context, snapshot) {
return TextField(
onChanged: onChanged,
keyboardType: type != null ? type : null,
decoration: InputDecoration(
icon: icon == null ? null : Icon(icon, color: Colors.white,),
hintText: hint,
hintStyle: TextStyle(color: Colors.white),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).primaryColor)
),
contentPadding: EdgeInsets.only(
left: 5,
right: 30,
bottom: 30,
top: 30
),
errorText: snapshot.hasError ? snapshot.error : null
),
style: TextStyle(color: Colors.white),
obscureText: obscure,
);
}
);
}
}
This is where I initialize the input types:这是我初始化输入类型的地方:
return Padding(
padding: EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
InputField(
icon: Icons.person_outline,
hint: "Nome do aniversariante",
obscure: false,
type: TextInputType.text,
stream: _birthdayBloc.outName,
onChanged: _birthdayBloc.changeName,
),
InputField(
icon: Icons.phone,
hint: "Telefone",
obscure: false,
type: TextInputType.text,
stream: _birthdayBloc.outPhone,
onChanged: _birthdayBloc.changePhone,
),
InputField(
icon: Icons.email,
hint: "E-mail",
obscure: false,
type: TextInputType.text,
stream: _birthdayBloc.outEmail,
onChanged: _birthdayBloc.changeEmail,
),
DropdownWidget(
isCenter: false,
icon: Icons.list,
arrowIcon: Icons.keyboard_arrow_down,
hint: "Selecione uma categoria",
items: _birthdayBloc.getCategoryList(),
stream: _birthdayBloc.outCategory,
onChanged: _birthdayBloc.changeCategory,
),
DropdownWidget(
isCenter: false,
icon: Icons.notifications,
arrowIcon: Icons.keyboard_arrow_down,
hint: "Selecione a notificação",
items: _birthdayBloc.getNotificationList(),
stream: _birthdayBloc.outNotification,
onChanged: _birthdayBloc.changeNotification,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 5,
child: DropdownWidget(
isCenter: false,
label: "Mês",
icon: Icons.calendar_today,
arrowIcon: Icons.keyboard_arrow_down,
hint: "Selecione o mês",
items: _birthdayBloc.getMonthsList(),
stream: _birthdayBloc.outMonth,
onChanged: _birthdayBloc.changeMonth,
),
),
Expanded(
flex: 5,
child: DropdownWidget(
isCenter: false,
label: "Dia",
arrowIcon: Icons.keyboard_arrow_down,
hint: "Selecione o dia",
items: _birthdayBloc.getDaysList(),
stream: _birthdayBloc.outDay,
onChanged: _birthdayBloc.changeDay,
),
),
],
),
DropdownWidget(
isCenter: false,
label: "Ano de nascimento",
icon: Icons.perm_contact_calendar,
arrowIcon: Icons.keyboard_arrow_down,
hint: "Selecione o ano",
items: _birthdayBloc.getYearsList(),
stream: _birthdayBloc.outYear,
onChanged: _birthdayBloc.changeYear,
valueController: 'Não sei'
),
Here is the code that retrieves the data from Firebase
when the screen is loaded:这是在加载屏幕时从
Firebase
检索数据的代码:
Future<void> _loadSelectedBirthday(personId) async {
String _userUid = await _getCurrentUserUid();
await _firestore.collection('birthdays').document(_userUid).collection('birthdays').document(personId).get()
.then((document) {
_nameController.add(document.data["name"]);
_phoneController.add(document.data["phone"]);
_emailController.add(document.data["email"]);
_categoryController.add(document.data["category"]);
_notificationController.add(document.data["notification"]);
_monthController.add(document.data["month"]);
_dayController.add(document.data["day"]);
_yearController.add(document.data["year"]);
print(_nameController.value);
print(_phoneController.value);
print(_emailController.value);
print(_categoryController.value);
print(_notificationController.value);
print(_monthController.value);
print(_dayController.value);
print(_yearController.value);
_stateController.add(BirthdayState.READY);
}).catchError((error) {
print('ERROR => $error');
});
}
The output I get from the prints above is:我从上面的打印中得到的输出是:
I/flutter (10907): Person Name
I/flutter (10907): 62999991234
I/flutter (10907): someemail@gmail.com
I/flutter (10907): Familiar
I/flutter (10907): No dia
I/flutter (10907): 3
I/flutter (10907): 25
I/flutter (10907): 1996
And here is the print from the app screen:这是应用程序屏幕上的打印内容:
Looks like you missed TextField initialization with value, that is why field is missing data.看起来您错过了带值的 TextField 初始化,这就是字段缺少数据的原因。 TextField can be initialized via its controller property:
TextField 可以通过其控制器属性进行初始化:
...
return TextField(
controller: TextEditingController(text: snapshot.data), // <--
keyboardType: type != null ? type : null,
onChanged: onChanged,
...
Therefore it could be not the best way to init text field this way in StreamBuilder.因此,它可能不是在 StreamBuilder 中以这种方式初始化文本字段的最佳方式。 Depending on your requirements it could be better to:
根据您的要求,最好是:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.