如何在没有无限循环的情况下调用 setState?
How to call setState without getting an infinite loop?
我有一个StatefulWidget,它需要检索存储在SharePreferences中的用户帐户变量,以在widget的显示和修改表单中显示它的所有数据。
我能够在表单中读取和显示这些变量,但是当我更新帐户和 SharedPreferences 变量时出现问题。使用此代码,当所有内容都已更新时,我的表单也会使用新变量进行更新。但碰巧我得到了一个无限循环,因为我成功的 SnackBar 一次又一次地弹出。
如果我不在我的 SnackBar 之前调用 _loadAccount(),该消息会出现一次。
如何纠正这个无限循环?哪个组件导致了这个无限构建?
class AccountForm extends StatefulWidget {
final AccountBloc accountBloc;
AccountForm({
Key key,
@required this.accountBloc
}) : super(key: key);
@override
State<AccountForm> createState() => _AccountFormState();
}
class _AccountFormState extends State<AccountForm> {
Account _account;
SharedPreferences prefs;
@override
void initState() {
super.initState();
_loadAccount();
}
void _loadAccount() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
Map accountMap = json.decode(prefs.getString('account'));
setState(() {
_account = Account.fromJson(accountMap);
});
}
@override
Widget build(BuildContext context) {
return _account == null ? new Container() :
new BlocBuilder<AccountEvent, AccountState>(
bloc: _accountBloc,
builder: (BuildContext context, AccountState state) {
if(state is AccountSuccess) {
_loadAccount();
_onWidgetDidBuild(() {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.message}'),
backgroundColor: Colors.green,
),
);
});
}
return new DefaultTabController(
//...
body: new TabBarView(
children: <Widget>[
new ListView( // Display form
children: [
new ListTile(
leading: Icon(Icons.person),
title: Text('Name'),
subtitle: Text(_account.lastName + " " +
_account.firstName)
),
//...
),
new Form( // Modification form
//...
)
]
)
)
);
}
);
}
void _onWidgetDidBuild(Function callback) {
WidgetsBinding.instance.addPostFrameCallback((_) {
callback();
});
}
}
不,我找不到解决方案。所以我改变了整个处理事件的系统,改用了 BLOC 系统。有了它,它工作得更好,不再有循环。还是谢谢
我有一个StatefulWidget,它需要检索存储在SharePreferences中的用户帐户变量,以在widget的显示和修改表单中显示它的所有数据。
我能够在表单中读取和显示这些变量,但是当我更新帐户和 SharedPreferences 变量时出现问题。使用此代码,当所有内容都已更新时,我的表单也会使用新变量进行更新。但碰巧我得到了一个无限循环,因为我成功的 SnackBar 一次又一次地弹出。
如果我不在我的 SnackBar 之前调用 _loadAccount(),该消息会出现一次。
如何纠正这个无限循环?哪个组件导致了这个无限构建?
class AccountForm extends StatefulWidget {
final AccountBloc accountBloc;
AccountForm({
Key key,
@required this.accountBloc
}) : super(key: key);
@override
State<AccountForm> createState() => _AccountFormState();
}
class _AccountFormState extends State<AccountForm> {
Account _account;
SharedPreferences prefs;
@override
void initState() {
super.initState();
_loadAccount();
}
void _loadAccount() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
Map accountMap = json.decode(prefs.getString('account'));
setState(() {
_account = Account.fromJson(accountMap);
});
}
@override
Widget build(BuildContext context) {
return _account == null ? new Container() :
new BlocBuilder<AccountEvent, AccountState>(
bloc: _accountBloc,
builder: (BuildContext context, AccountState state) {
if(state is AccountSuccess) {
_loadAccount();
_onWidgetDidBuild(() {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.message}'),
backgroundColor: Colors.green,
),
);
});
}
return new DefaultTabController(
//...
body: new TabBarView(
children: <Widget>[
new ListView( // Display form
children: [
new ListTile(
leading: Icon(Icons.person),
title: Text('Name'),
subtitle: Text(_account.lastName + " " +
_account.firstName)
),
//...
),
new Form( // Modification form
//...
)
]
)
)
);
}
);
}
void _onWidgetDidBuild(Function callback) {
WidgetsBinding.instance.addPostFrameCallback((_) {
callback();
});
}
}
不,我找不到解决方案。所以我改变了整个处理事件的系统,改用了 BLOC 系统。有了它,它工作得更好,不再有循环。还是谢谢