Если я использую Hero и Multiprovider вместе, я получаю сообщение об ошибке
У меня есть список карт. Когда я нажимаю на карту, BoxViewPage открыт
С Героем и без МультиПровайдера все работает корректно,
Без Героя и с Мультипровайдером все работает корректно,
но
Если я использую Hero и Multiprovider вместе, я получаю сообщение об ошибке
return Hero(
tag: boxID,
child: InkWell(
child: selectBoxSize(viewType),
onTap: () async {
// String path = GetArchiveLocalPath(archives, archive);
// Box.addPhotosFromShared(path, box);
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => MultiProvider(
providers: [
ChangeNotifierProvider<Archive>.value(value: archive),
ChangeNotifierProvider<Box>.value(value: box),
],
builder: (context, child) => BoxViewPage(),
),
),
class BoxCardView extends StatefulWidget {
const BoxCardView({Key key}) : super(key: key);
@override
_BoxCardViewState createState() => _BoxCardViewState();
}
class _BoxCardViewState extends State<BoxCardView> {
@override
Widget build(BuildContext context) {
return Hero(
tag: boxID,
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
margin: EdgeInsets.all(12),
child: Column(
children: <Widget>[
Expanded(child: WidgetEditPhotosScrollHoriz()),
WidgetNameDescrTagsEdit(),
],
),
),
);
}
}
Ошибка:
Мы проверили исправление ProviderNotFoundException (ошибка: не удалось найти нужного поставщика выше этого виджета WidgetEditPhotosScrollHoriz).
Это происходит из-за того, что вы использовали провайдера, который не включает выбранного вами провайдера. Есть несколько распространенных сценариев:
Вы добавили нового провайдера в свой
main.dart
и выполнил горячую перезагрузку. Чтобы исправить, выполните горячий перезапуск.Поставщик, которого вы пытаетесь прочитать, находится на другом маршруте.
Провайдеры ограничены. Поэтому, если вы вставите провайдера внутрь маршрута, другие маршруты не смогут получить доступ к этому провайдеру.
Вы использовали
BuildContext
это предок провайдера, который вы пытаетесь прочитать.Убедитесь, что WidgetEditPhotosScrollHoriz находится под вашим MultiProvider/Provider. Обычно это происходит, когда вы создаете провайдера и пытаетесь сразу его прочитать.
Например, вместо:
Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // Will throw a ProviderNotFoundError, because `context` is associated // to the widget that is the parent of `Provider<Example>` child: Text(context.watch<Example>()), ), }
рассмотрите возможность использования
builder
вот так:Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // we use `builder` to obtain a new `BuildContext` that has access to the provider builder: (context) { // No longer throws return Text(context.watch<Example>()), } ), }
Если ни одно из этих решений не работает, рассмотрите возможность обратиться за помощью в StackOverflow:https://stackoverflow.com/questions/tagged/flutter)
2 ответа
Насколько я понимаю, я думаю, что ваша проблема также является одной из типичных при использовании провайдеров.
Я всегда рекомендую использовать провайдер в корне вашего приложения (выше MaterialApp), это в основном лучший способ использовать его без ошибок.
Вы видите, что на самом деле здесь происходит, что провайдеры работают на основе иерархии (они предоставляют определенное значение для всех виджетов и суб-виджетов, которые вы можете сказать), и я уверен, что вы также ожидали этого, но когда мы используем навигатор вместо это родительско-дочернее отношение между виджетами - это скорее родственное отношение между страницами. Обратите внимание, что здесь я использовал слово «страницы». Ваш провайдер для вашего случая предоставляет значение только для подвиджетов той конкретной страницы, где вы его использовали, когда вы переходите на новую страницу, которая сейчас находится в верхней части стека навигации. это не подвиджет, а своего рода родственное отношение, и поэтому вы не можете получить доступ к провайдеру здесь.
Если вы этого не понимаете, не беспокойтесь, самое простое решение и визуализация для этого — просто открыть инструменты разработки dart в браузере и в инспекторе виджетов. Проверьте иерархию виджетов, вы увидите, что виджет, в котором вы хотите использовать значение, предоставленное провайдером, не находится в этой иерархии. Теперь вам нужно только выяснить, что вы должны сделать, чтобы это произошло.
Одно решение, которое я могу дать, - это просто использовать провайдера в корне приложения (выше MaterialApp).
Не могли бы вы попробовать это в своем файле списка карт:
MaterialPageRoute(
builder: (BuildContext context) => MultiProvider(
providers: [
ChangeNotifierProvider<Archive>(
create: (BuildContext context) => Archive()
),
ChangeNotifierProvider<Box>(
create: (BuildContext context) => Box()
),
],
builder: (context, child) => BoxViewPage(),
),
),