我有一个包含名称、id、卡路里等属性的 Food 对象。通过一系列屏幕,用户填充食物对象属性。
完成后,用户可以按下提交按钮,这将调用商店中的 addFood 方法。
问题是,将食物上传到服务器后,我想根据响应弹出屏幕或在 toast 中显示错误消息。我只是不知道该怎么做。
以下是我的代码(只有重要的部分):
FoodDetailStore.dart
class FoodDetailStore = _FoodDetailStore with _$FoodDetailStore;
abstract class _FoodDetailStore with Store {
Repository _repository;
Food _food;
@observable
String msg = '';
// ... Other Observables and actions
@action
addFood(bool toAdd) {
if (toAdd) {
_repository.addFood(food).then((docId) {
if (docId != null) {
// need to pop the screen
}
}).catchError((e) {
// show error to the user.
// I tried this, but it didn't work
msg = 'there was an error with message ${e.toString()}. please try again.';
});
}
// .. other helper methods.
}
FoodDetailScreen.dart (忽略 bloc 引用,我目前正在将代码重构为 mobx)
class FoodDataScreen extends StatefulWidget {
final String foodId;
final Serving prevSelectedServing;
final bool fromNewRecipe;
FoodDataScreen({@required this.foodId, this.prevSelectedServing, this.fromNewRecipe});
@override
_FoodDataScreenState createState() => _FoodDataScreenState(
this.foodId,
this.prevSelectedServing,
this.fromNewRecipe,
);
}
class _FoodDataScreenState extends State<FoodDataScreen> {
final String foodId;
final Serving prevSelectedServing;
final bool fromNewRecipe;
FoodDataBloc _foodDataBloc;
_FoodDataScreenState(
this.foodId,
this.prevSelectedServing,
this.fromNewRecipe,
);
FoodDetailStore store;
@override
void initState() {
store = FoodDetailStore();
store.initReactions();
store.initializeFood(foodId);
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
// I know this is silly, but this is what i tried. Didn't worked
Observer(
builder: (_) {
_showMsg(store.msg);
}
);
}
@override
Widget build(BuildContext context) {
return Container(
// ... UI
);
}
_popScreen() {
_showMsg('Food Added');
Majesty.router.pop(context);
}
_showMsg(String msg) {
Fluttertoast.showToast(msg: msg);
}
@override
void dispose() {
store.dispose();
super.dispose();
}
}
最佳答案
正如您已经正确指出的那样,在 Observer
中构建 didChangeDependencies()
实例确实是“愚蠢的”:)Observer
是一个小部件,小部件需要插入到小部件树中才能做一些有用的事情。在我们的例子中,non-widget Mobx reactions 来帮忙。
对于在可观察到的更改时显示 Snackbar
的情况,我将在我的代码中展示我是如何做到的,以便您了解如何转换您的代码。
首先,导入 import 'package:mobx/mobx.dart';
。
然后在 didChangeDependencies()
中创建一个 react ,它将使用您的一些观察值。在我的例子中,这些 observables 是 _authStore.registrationError
和 _authStore.loggedIn
:
final List<ReactionDisposer> _disposers = [];
@override
void dispose(){
_disposers.forEach((disposer) => disposer());
super.dispose();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_authStore = Provider.of<AuthStore>(context);
_disposers.add(
autorun(
(_) {
if (_authStore.registrationError != null)
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text(_authStore.registrationError),
backgroundColor: Colors.redAccent,
duration: Duration(seconds: 4),
),
);
},
),
);
_disposers.add(
reaction(
(_) => _authStore.loggedIn,
(_) => Navigator.of(context).pop(),
),
);
}
我在这里使用两种类型的 Mobx react :
autorun
和 reaction
。 autorun
在您创建它后立即第一次触发,然后每次可观察值更改其值。 reaction
不会第一次触发,只有在 observable 发生变化时才会触发。还要注意在
dispose()
方法中处理创建的 react ,以避免资源泄漏。这是我的 Mobx 商店类的代码,其中使用了 observable 来完成图片:
import 'package:mobx/mobx.dart';
import 'dart:convert';
part "auth_store.g.dart";
class AuthStore = AuthStoreBase with _$AuthStore;
abstract class AuthStoreBase with Store{
@observable
String token;
@observable
String registrationError;
@observable
String loginError;
@action
void setToken(String newValue){
token = newValue;
}
@action
void setRegistrationError(String newValue){
registrationError = newValue;
}
@action
void setLoginError(String newValue){
loginError = newValue;
}
@action
void resetLoginError(){
loginError = null;
}
@computed
bool get loggedIn => token != null && token.length > 0;
@action
Future<void> logOut() async{
setToken(null);
}
}
关于flutter - 如何在 flutter 中使用 Mobx 弹出屏幕,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56412277/