Я новичок в мире флаттера и разработке мобильных приложений и борюсь с тем, как я должен передавать пользовательские данные во всем приложении.
Я пробовал несколько вещей, но никто не кажется большим, и я уверен, что есть лучшие образцы практики, которые я должен соблюдать.
Поскольку это упрощает примеры, я использую firebase для аутентификации. У меня в настоящее время есть отдельный маршрут для входа в систему. Как только я войду в систему, я хочу, чтобы модель User в большинстве представлений проверяла разрешения на то, что показывать, отображая информацию пользователя в ящике и т.д.
У Firebase есть await firebaseAuth.currentUser();
. Лучше ли называть это везде, где может понадобиться пользователь? и если да, то где лучше всего разместить этот звонок?
flutter codelab показывает отличный пример аутентификации пользователей до разрешения записи. Однако, если странице необходимо проверить auth, чтобы определить, что нужно построить, асинхронный вызов не может идти в методе build
.
initState
Один из методов, который я пробовал, - это переопределить initState и запустить вызов, чтобы получить пользователя. Когда будущее завершается, я вызываю setState
и обновляю пользователя.
FirebaseUser user;
@override
void initState() {
super.initState();
_getUserDetail();
}
Future<Null> _getUserDetail() async {
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}
Это работает прилично, но кажется, что для каждого виджета, который ему нужен, очень много. Существует также вспышка, когда экран загружается без пользователя, а затем обновляется с пользователем при завершении в будущем.
Передайте пользователя через конструктор
Это тоже работает, но очень много шаблонов для передачи пользователю через все маршруты, представления и их состояния, которые могут потребоваться для доступа к ним. Кроме того, мы не можем просто делать popAndPushNamed
при переходе по маршрутам, потому что мы не можем передать ему переменную. Мы должны изменить маршруты, подобные этому:
Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) => new MyPage(user),
));
Унаследованные виджеты
https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1
В этой статье был показан хороший шаблон для использования InheritedWidget
. Когда я помещаю унаследованный виджет на уровне MaterialApp, дети не обновляются при изменении состояния auth (я уверен, что я делаю это неправильно)
FirebaseUser user;
Future<Null> didChangeDependency() async {
super.didChangeDependencies();
User currentUser = await firebaseAuth.currentUser();
setState(() => user = currentUser);
}
@override
Widget build(BuildContext context) {
return new UserContext(
user,
child: new MaterialApp(
title: 'TC Stream',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new LoginView(title: 'TC Stream Login', analytics: analytics),
routes: routes,
),
);
}
FutureBuilder
FutureBuilder также кажется достойным вариантом, но, похоже, для каждого маршрута много работы. В частичном примере ниже _authenticateUser()
получает состояние пользователя и настройки после завершения.
@override
Widget build(BuildContext context) {
return new FutureBuilder<FirebaseUser>(
future: _authenticateUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return _buildProgressIndicator();
}
if (snapshot.connectionState == ConnectionState.done) {
return _buildPage();
}
},
);
}
Я был бы признателен за любые советы по шаблонам лучшей практики или ссылки на ресурсы, которые можно использовать для примеров.