使用ViewModel时导航到新屏幕并传递redux存储状态

时间:2019-01-27 21:32:20

标签: redux architecture dart flutter flutter-redux

我需要将Redux存储状态从屏幕传递到build函数中的另一个屏幕。
我的问题是在build函数中,我有ViewModel变量,该变量没有对状态的引用。

这是屏幕的代码:

import ...

class Menu extends StatefulWidget {
  @override
  _MenuState createState() => _MenuState();
}

class _MenuState extends State<Menu> {

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, ViewModelLogin>(
      converter: (store) => ViewModelLogin.create(store),
      builder: (context, ViewModelLogin viewModel) {
        Widget _buildPage(isLoggedIn) {
          if (isLoggedIn) {
            return ListView(
              children: <Widget>[
                ListTile(
                  title: Text('Settings'),
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => MySettingsScreen(), // <-- HERE I NEED TO PASS THE STATE TO MySettingsScreen
                      ),
                    );
                  },
                ),
                ListTile(
                    leading: Image.network(
                      viewModel.loginType == 'facebook'
                          ? 'https://img.icons8.com/color/52/000000/facebook.png'
                          : 'https://image.flaticon.com/teams/slug/google.jpg'
                      ,
                      width: 30.0,
                    ),
                    title: Text('Exit'),
                    onTap: () {
                      viewModel.onLogout(viewModel.loginType);
                    }
                ),
              ],
            );
          } else {
            return LoginScreen(appBar: false);
          }
        }

        return _buildPage(viewModel.isLoggedIn);
      },
    );
  }
}

我需要将状态传递给MySettingsScreen的原因是,在屏幕上,我需要一个store变量来对Web服务(构建函数外部)进行get调用。

这是MySettingsScreen的一部分,我需要其中的存储状态:

import ...

class MySettingsScreen extends StatefulWidget {
  final AppState state;

  MySettingsScreen({Key key, @required this.state}) : super(key: key);

  @override
  _MySettingsScreenState createState() => _MySettingsScreenState();
}

class _MySettingsScreenState extends State<MySettingsScreen> {
  @override
  void initState() {
    super.initState();

    _load();
  }

  void _load() async {
    final url = 'url';

    try {
      http.Response res = await http.get(url, headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + // <-- HERE I NEED THE STORE VARIABLE
      });
      final data = json.decode(res.body);
      tmpItems = _parseItems(data["bookings"]);
    } catch(e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    ...
  }
}

1 个答案:

答案 0 :(得分:0)

对于整个应用范围状态的最常见用例,您只需在需要该状态的任何屏幕中使用StoreConnector。您已经在Menu类中使用了它,但是可以在MySettingsScreen构建方法替代中类似地使用它。

此外,还使用存储库来创建视图模型,因此其想法是,在构建视图模型时,您将包含存储库中构建视图所需的所有信息。例如:

class MyViewModel {
    String myInfo;
    factory MyViewModel.create(Store<AppState> store) {
        return MyViewModel(myInfo: store.state.myInfoState);
    }
...
}

然后您使用视图模型中的信息:

  @override
  Widget build(BuildContext context) => StoreConnector<AppState, MyViewModel>(
    converter: (Store<AppState> store) => MyViewModel.create(store),
    builder: (BuildContext context, MyViewModel viewModel) {
      return Text(viewModel.myInfo);
  }

您可以使用相同的机制在viewModel中保留对商店的引用:

class MyViewModel {
    Store<AppState> myStore;
    factory MyViewModel.create(Store<AppState> store) {
        return MyViewModel(myStore: store);
    }
...
}

这允许您直接在构建方法中使用它:

  @override
  Widget build(BuildContext context) => StoreConnector<AppState, MyViewModel>(
    converter: (Store<AppState> store) => MyViewModel.create(store),
    builder: (BuildContext context, MyViewModel viewModel) {
      return Text(viewModel.myStore.state.myInfo);
  }

请注意,如果要在视图模型和redux持久性之间保持逻辑分离,则最好使用第一种模式。