Перейдите к новому экрану и передавая состояние хранилища приставки при использовании модели представления
У меня есть необходимость передать состояние магазина приставки с экрана на другой внутри 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, заключается в том, что на экране мне нужна переменная хранилища, чтобы выполнить вызов 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 ответ
Для наиболее распространенного случая использования состояния приложения вы можете просто использовать StoreConnector
на любом экране, где вам нужно состояние. Вы уже используете его в своем классе меню, но вы можете использовать его аналогично в вашем классе 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);
}
Обратите внимание, что первый шаблон может быть предпочтительным, если вы хотите сохранить логическое разделение между моделью представления и постоянством избыточности.