flutter - 如何在 flutter 中使用 Mobx 弹出屏幕

标签 flutter dart mobx

我有一个 Food 对象,其中包含名称、ID、卡路里等属性。通过一系列屏幕,用户填充食物对象属性。

完成后,用户可以按下提交按钮,这将调用商店中的 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();
  }
}

最佳答案

didChangeDependencies() 中构造一个 Observer 实例确实是“愚蠢的”,正如您已经正确指出的那样:) Observer 是一个小部件,需要将小部件插入到小部件树中才能执行一些有用的操作。在我们的案例中 non-widget Mobx reactions前来救援。

我将在我的代码中展示我是如何在可观察到的变化时显示 Snackbar 的,这样您就会了解如何转换您的代码。

首先,导入import 'package:mobx/mobx.dart';。 然后在 didChangeDependencies() 中创建一个将使用您的一些可观察对象的 react 。在我的例子中,这些可观察对象是 _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 不会第一次触发,只有当可观察到的变化时才触发。

另外注意在dispose()方法中dispose创建的reactions,避免资源泄露。

这是我的 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);
  }
}

关于flutter - 如何在 flutter 中使用 Mobx 弹出屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56412277/

相关文章:

android - Flutter firebase_auth signInWithCredential 不适用于 android

if-statement - dart 替代很多 if else if

firebase - Flutter 如何允许用户创建和切换多个账户?

oauth - 无法理解 Aqueduct 自动生成的数据库和身份验证

javascript - console.log打印两次并且map在reactjs/mobx项目中不起作用

flutter - 如何在全局范围内使用这种方法?

flutter - 在Flutter中按下按钮后更新文本

windows - 如何构建 Windows 应用程序的发布版本?

javascript - Mobx 性能

reactjs - 让 typescript 看到装饰器的 Prop