我有一个包含名称、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 : autorunreactionautorun 在您创建它后立即第一次触发,然后每次可观察值更改其值。 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/

10-10 17:50