Перейдите к новому экрану и передавая состояние хранилища приставки при использовании модели представления - PullRequest
0 голосов
/ 28 января 2019

У меня есть необходимость передать состояние избыточного хранилища с экрана на другой внутри функции 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, заключается в том, что на экране мне нужна переменная хранения, чтобы сделатьполучить вызов веб-службы (вне функции сборки).

Это часть 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 голосов
/ 28 января 2019

Для наиболее распространенного случая использования состояния приложения можно просто использовать 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);
  }

Вы можете использовать тот же механизм для сохранения ссылки на хранилище в модели представления:

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);
  }

Обратите внимание, что первый шаблон может быть предпочтительным, если вы хотите сохранить логическое разделение между моделью представления и избыточностьюсохранение.

...