我有一个Food对象,该对象包含名称,id,卡路里等属性。通过一系列屏幕,用户可以填充Food对象的属性。
完成后,用户可以按“提交”按钮,这将在商店中调用addFood方法。
问题是,将食物上传到服务器后,我想根据响应弹出屏幕或在烤面包上显示错误消息。我只是不知道该怎么做。
以下是我的代码(仅重要位): 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 (忽略集团参考,我目前正在将代码重构为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();
}
}
答案 0 :(得分:3)
在Observer
内构造didChangeDependencies()
实例确实是“愚蠢的”,正如您已经正确指出的那样:)
Observer
是一个窗口小部件,需要将窗口小部件插入窗口小部件树中才能执行有用的操作。在我们的情况下,non-widget Mobx reactions进行了救援。
对于在发生明显变化时显示Snackbar
的情况,我将在代码中演示如何做到这一点,以便您了解如何转换代码。
首先,导入import 'package:mobx/mobx.dart';
。
然后在didChangeDependencies()
中创建一个反应,该反应将使用您的一些观测值。在我的情况下,这些可观察对象是_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反应:autorun
和reaction
。 autorun
会在您创建板条之后立即触发,然后每次观察对象更改其值。 reaction
仅在可观察到的变化时才触发第一次。
还应注意以dispose()
方法处理已创建的反应,以避免资源泄漏。
这是我的Mobx商店类的代码,其中使用了可观察的东西来完成图片:
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);
}
}