我有一个包含名称、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.
}
Run Code Online (Sandbox Code Playgroud)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
正如您已经正确指出的那样,Observer在内部构造一个实例didChangeDependencies()确实是“愚蠢的”:)
Observer是一个小部件,并且小部件需要插入到小部件树中才能做一些有用的事情。在我们的例子中,非小部件 Mobx 反应就派上用场了。
我将在我的代码中展示如何在我的代码中展示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(),
),
);
}
Run Code Online (Sandbox Code Playgroud)
我在这里使用两种类型的 Mobx 反应:autorun和reaction. autorun在您创建它后立即触发第一次,然后每次可观察值更改其值。reaction不会在第一次触发,只有在 observable 发生变化时才会触发。
还要注意在dispose()方法中处理创建的反应,避免资源泄漏。
这是我的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3999 次 |
| 最近记录: |