Я пытаюсь абстрагировать свою навигацию, помещая всю логику в класс. Я не использую какой-либо пакет для навигации и использую Provider для управления состоянием. Я понял, что поставщики не работают, если они находятся в переменной, а не в функции.
Примерно это я пытаюсь сделать:
class AppRoutes {
static void push(
BuildContext context, {
required Routes route,
}) {
Navigator.of(context).push(
_getRoute(route: route),
);
}
static void replace(
BuildContext context, {
required Routes route,
}) {
Navigator.of(context).pushReplacement(
_getRoute(route: route),
);
}
static void pushAndRemoveUntil(
BuildContext context, {
required Routes route,
}) {
Navigator.of(context).pushAndRemoveUntil(
_getRoute(route: route),
(Route<dynamic> routeFn) => false, // Remove all the routes
);
}
static MaterialPageRoute<dynamic> _getRoute({
required Routes route,
}) {
bool _isLoggedIn = GetIt.instance.isRegistered<User>();
return MaterialPageRoute<dynamic>(
builder: (_) => switch (route) {
Routes.login => _isLoggedIn ? homePage : loginPage,
//rest of routes
_ => _notFoundPage,
},
);
}
static ChangeNotifierProvider get loginPage => ChangeNotifierProvider(
create: (_) => LoginController(),
child: LoginView(),
);
//rest of pages
}
Это вызывает у меня проблему: провайдер не найден в контексте:
Ошибка: не удалось найти правильного поставщика выше. этот виджет ProfileView
Это происходит потому, что вы использовали
BuildContext, который не включает поставщик по вашему выбору.
Однако этого не происходит, когда поставщик помещается непосредственно в функцию вместо использования промежуточных функций или переменных. Итак, если я сделаю это вот так, это сработает:
static void push(
BuildContext context, {
required Routes route,
}) {
Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (_) => ChangeNotifierProvider(
create: (_) => ProfileController(),
child: ProfileView(),
),
),
);
}
Он также работает с предыдущим кодом, но в качестве поставщиков используются MultiProviders, а не ChangeNotifierProvider:
static MultiProvider get _profilePage => MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ProfileController()),
],
child: ProfileView(),
);
Может ли кто-нибудь сказать мне, почему это происходит и как я могу решить эту проблему, не превращая всех моих одиночных провайдеров в мультипровайдеров?





В этом случае провайдер работает нормально, проблема заключается в следующем коде:
static ChangeNotifierProvider get loginPage => ChangeNotifierProvider(
create: (_) => LoginController(),
child: LoginView(),
);
Это возвращает ChangeNotifierProvider с динамическим типом. И когда вы пытаетесь найти поставщика на странице входа в систему с помощью context.read() или Consumer(), поставщик не может его найти, поскольку ChangeNotifierProvider существует с динамическим типом. Чтобы это исправить, измените код на следующий:
static ChangeNotifierProvider<LoginController> get loginPage => ChangeNotifierProvider<LoginController>(
create: (_) => LoginController(),
child: LoginView(),
);
Это должно работать так, как ожидалось.