1

我需要将 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 服务(在构建函数之外)。

这是我需要商店状态的 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) {
    ...
  }
}
4

1 回答 1

2

对于应用程序范围状态的最常见用例,您可以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 中保留对 store 的引用:

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 持久性之间保持逻辑分离,第一种模式可能更可取。

于 2019-01-27T23:15:20.220 回答