#flutter #dart #flutter-provider #flutter-navigation
#трепещущий #dart #трепетание-поставщик #трепещущая навигация
Вопрос:
Я только начал использовать provider в качестве управления состоянием для flutter. У меня есть значение в поставщике, которое будет использоваться для первоначального входа в систему. isLogin вернет true или false и в зависимости от этого перенаправит пользователя на домашнюю страницу или страницу входа в систему. Я получаю сообщение об ошибке ниже:
Не удалось найти правильного поставщика над этим виджетом MyApp
Кроме того, это хороший способ проверки подлинности или есть лучший способ. Я использую laravel API для аутентификации.
Main.dart
void main() {
runApp(MyApp());
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<UserProvider>(
create: (context) => UserProvider(),
child: MaterialApp(
initialRoute:Provider.of<UserProvider>(context,listen:false).isLogin?'/':'/login',
routes: {
'/':(_)=>HomePage(),
'/donation-history':(_)=>DonationHistoryPage(),
'/login':(_)=>LoginPage(),
'/new-donation':(_)=>NewDonation()
},
debugShowCheckedModeBanner:false,
title: 'RedHero',
theme: ThemeData(
primaryColor: kPrimaryColor,
accentColor: Colors.white,
scaffoldBackgroundColor: kBackgroundColor,
fontFamily: "Poppins",
textTheme: TextTheme(
bodyText1: TextStyle(color: kBodyTextColor)
)
),
),
);
}
Комментарии:
1. Все в порядке, но как насчет моей первоначальной проблемы? Я не могу найти ошибку, я проверяю дерево виджетов, и поставщик находится поверх всех моих маршрутов @ Uni
2. приведенный выше виджет принадлежит MyApp @Uni
Ответ №1:
Нарушенный шаблон:
class OuterWidget : StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Something>(
... Provider.of<Something>(context) ...
);
}
}
Проблема в том, что Provider.of<Something>
получает то же context
, что было передано build
функции. В этом контексте ChangeNotifierProvider
не существует; поставщик добавляется только в контексты сборки потомков, которые создаются при создании дочерних виджетов.
Если это неясно, представьте извлечение предоставленного объекта в переменную (что не меняет смысла кода):
class OuterWidget : StatelessWidget {
@override
Widget build(BuildContext context) {
final something = Provider.of<Something>(context);
return ChangeNotifierProvider<Something>(
... something ...
);
}
}
Теперь совершенно очевидно, что мы пытаемся использовать объект, который еще не был предоставлен.
Таким образом, одним из решений является разделение внутренней части на отдельный виджет:
class OuterWidget : StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Something>(
... InnerWidget() ...
);
}
}
class InnerWidget : StatelessWidget {
@override
Widget build(BuildContext context) {
return ... Provider.of<Something>(context) ...;
}
}
Этот виджет получит новый дочерний контекст, в котором поставщик действительно существует.
Другим решением является использование Consumer
виджета, который существует именно для этого сценария:
class OuterWidget : StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Something>(
...
Consumer<Something>(builder: (_, something, __) => ... something ...)
...
);
}
}
Теперь сборка дочерних элементов Consumer
откладывается до builder
метода, который, следовательно, также получает контекст сборки, в котором существует поставщик.