StreamBuilder 中的 TextField 丢失了编辑后的值
TextField inside StreamBuilder lost the edited values
我正在为一个应用程序开发用户配置文件更新页面,我遇到了问题,为了用初始数据填充表单,我使用了 StreamBuilder
并使用 TextEditingController
将数据加载到 TextField
,数据加载正常并且运行良好,但问题是当我尝试更改 TextField
并专注于下一个 TextField
StreamBuilder
使用之前加载并丢失的数据刷新 ui编辑的数据。在这种情况下,Stream 不会从网络调用中更新。有人遇到过这种情况吗?或任何推荐的方法来做到这一点?请帮忙。
代码
class UserProfileScreen extends StatefulWidget {
@override
_UserProfileScreenState createState() => _UserProfileScreenState();
}
class _UserProfileScreenState extends State<UserProfileScreen> {
UserProfileBloc userBloc;
final firstNameController = TextEditingController();
final surnameNameController = TextEditingController();
final phoneController = TextEditingController();
final emailController = TextEditingController();
var _hashCode = 0;
@override
void initState() {
super.initState();
userBloc = UserProfileBloc();
userBloc.getUser();
}
@override
void dispose() {
userBloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
leading: IconButton(
icon: Icon(
Icons.close,
color: ColorPallet.white,
),
onPressed: () {
if (Navigator.canPop(context)) {
Navigator.pop(context);
}
},
)
),
body: buildUserProfileContent(context),
);
}
Container buildUserProfileContent(BuildContext context) {
return Container(
child: StreamBuilder<UserProfileState>(
stream: userBloc.user,
initialData: UserProfileInitState(),
builder: (context, snapshot) {
if (snapshot.data is UserProfileDataState) {
UserProfileDataState state = snapshot.data;
return buildProfileContent(state.user, state.profileImage);
}
},
),
);
//);
}
ListView buildProfileContent(User user, Uint8List profileImage) {
firstNameController.text = user.firstName;
return ListView(
children: <Widget>[
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
controller: firstNameController,
),
]
),
)],
);
}
}
问题发生在您在构建方法中设置值时。如果你想像上面那样设置值,在 class _UserProfileScreenState
维护一个变量 _initialized = false
并在初始化后使其成为 true
。
类似于:
if(!_initialized){
firstNameController.text = user.firstName;
_initialized = true;
}
希望对您有所帮助!
你应该按照我的代码使用onChange。
onChanged: (value) => {_onChangeValue()},
StreamBuilder(
initialData: true,
stream: _loginBloc.isToggledPass,
builder: (context, snapshot) {
return TextField(
controller: _passwordController,
obscureText: snapshot.data,
textInputAction: TextInputAction.done,
onChanged: (value) => {_onChangeValue()},
decoration: InputDecoration(
hintText: hintPassword,
);
}),
我正在为一个应用程序开发用户配置文件更新页面,我遇到了问题,为了用初始数据填充表单,我使用了 StreamBuilder
并使用 TextEditingController
将数据加载到 TextField
,数据加载正常并且运行良好,但问题是当我尝试更改 TextField
并专注于下一个 TextField
StreamBuilder
使用之前加载并丢失的数据刷新 ui编辑的数据。在这种情况下,Stream 不会从网络调用中更新。有人遇到过这种情况吗?或任何推荐的方法来做到这一点?请帮忙。
代码
class UserProfileScreen extends StatefulWidget {
@override
_UserProfileScreenState createState() => _UserProfileScreenState();
}
class _UserProfileScreenState extends State<UserProfileScreen> {
UserProfileBloc userBloc;
final firstNameController = TextEditingController();
final surnameNameController = TextEditingController();
final phoneController = TextEditingController();
final emailController = TextEditingController();
var _hashCode = 0;
@override
void initState() {
super.initState();
userBloc = UserProfileBloc();
userBloc.getUser();
}
@override
void dispose() {
userBloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
leading: IconButton(
icon: Icon(
Icons.close,
color: ColorPallet.white,
),
onPressed: () {
if (Navigator.canPop(context)) {
Navigator.pop(context);
}
},
)
),
body: buildUserProfileContent(context),
);
}
Container buildUserProfileContent(BuildContext context) {
return Container(
child: StreamBuilder<UserProfileState>(
stream: userBloc.user,
initialData: UserProfileInitState(),
builder: (context, snapshot) {
if (snapshot.data is UserProfileDataState) {
UserProfileDataState state = snapshot.data;
return buildProfileContent(state.user, state.profileImage);
}
},
),
);
//);
}
ListView buildProfileContent(User user, Uint8List profileImage) {
firstNameController.text = user.firstName;
return ListView(
children: <Widget>[
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
controller: firstNameController,
),
]
),
)],
);
}
}
问题发生在您在构建方法中设置值时。如果你想像上面那样设置值,在 class _UserProfileScreenState
维护一个变量 _initialized = false
并在初始化后使其成为 true
。
类似于:
if(!_initialized){
firstNameController.text = user.firstName;
_initialized = true;
}
希望对您有所帮助!
你应该按照我的代码使用onChange。
onChanged: (value) => {_onChangeValue()},
StreamBuilder(
initialData: true,
stream: _loginBloc.isToggledPass,
builder: (context, snapshot) {
return TextField(
controller: _passwordController,
obscureText: snapshot.data,
textInputAction: TextInputAction.done,
onChanged: (value) => {_onChangeValue()},
decoration: InputDecoration(
hintText: hintPassword,
);
}),