Поставщик пакетов Flutter с шаблонами

Я пытаюсь использовать поставщика с шаблоном, но Provider.of, похоже, не работает.

Журналы:

══╡ ИСКЛЮЧЕНИЕ, ЗАЯВЛЕННОЕ БИБЛИОТЕКОЙ ВИДЖЕТОВ ╞════════════════════════════════════════ ══════════════════ При построении MyChildWidget (грязный) возникла следующая ошибка ProviderNotFoundError: Ошибка: не удалось найти правильный поставщик над этим виджетом MyChildWidget

Чтобы исправить, пожалуйста:

  • Убедитесь, что поставщик является предком этого виджета MyChildWidget.
  • Предоставьте типы поставщику
  • Предоставьте типы потребителю
  • Предоставьте типы Provider.of ()
  • Всегда используйте импорт пакетов. Пример: пакет `import ': my_app / my_code.dart';
  • Убедитесь, что используется правильный context.

Вы знаете какое-нибудь решение?

Образец, демонстрирующий проблему:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Provider<MyChildState>.value(
          value: MyChildState("Hello world !"),
          child: MaterialApp(
            home: MyChildWidget(),
          )),
    );
  }
}

abstract class MyParentWidget<State extends MyParentState> extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final State state = Provider.of(context);
    return Text(state.text);
  }
}

abstract class MyParentState {
  final String text;

  MyParentState(this.text);
}

class MyChildWidget<MyChildState> extends MyParentWidget{
}

class MyChildState extends MyParentState {
  MyChildState(String text) : super(text);
}

person Lyofen    schedule 29.11.2019    source источник


Ответы (1)


При первом взгляде на ваш код я вижу, что вы передаете MyChildState("Hello world !") в качестве значения, но позже в классе MyParentWidget вы запрашиваете State объект final State state = Provider.of(context);.

Попробуйте запросить MyChildState вместо State.

Мое первое впечатление после прочтения вашего кода - это то, что вы пришли с другого языка программирования и теперь пробуете Flutter. Дружественный совет: делайте все как можно проще.

Вся абстракция и то, как организован код, могут сбить вас с толку позже, когда вы просмотрите код, который вы написали, вместо того, чтобы помочь вам.

person Andrei    schedule 29.11.2019
comment
Да, я с Android. Здесь я хотел бы поделиться логикой пользовательского интерфейса с «общим виджетом» для наследования. Я использую bloc для предоставления потока ‹State› для каждого виджета, но если 2 виджета имеют некоторую общую логику пользовательского интерфейса, я хотел бы извлечь эту логику внутри родительского виджета (так что родитель будет использовать родительское состояние для применения общей логики, а потомок может переопределить это поведение за его изменения). - person Lyofen; 29.11.2019
comment
Но, как вы сказали, я могу попытаться извлечь состояние, предоставленное родителем, каждый дочерний элемент восстанавливает свое состояние с помощью provider.of и создает методы в родительском виджете для вызова из дочерних элементов. - person Lyofen; 29.11.2019
comment
Я предлагаю вам пойти и попробовать несколько руководств и прочитать об управлении состоянием Flutter. Ваш взгляд на приложения Flutter немного сбивает с толку. В своих проектах я никогда не использовал абстрактные классы для целей пользовательского интерфейса, таких как родительский и дочерний, а затем родительский элемент имеет некоторые функции, которые дочерний элемент может переопределить. Обычно каждый виджет представляет собой элемент с экрана. Вы хотите смоделировать его как виджет, у которого есть дочерние элементы? Добавьте в конструктор дочерний аргумент, как это делает виджет Column. Я рекомендую вам ознакомиться с существующей реализацией виджетов, чтобы лучше понять Flutter. - person Andrei; 29.11.2019
comment
Например, для двух экранов мне нужно ввести адрес электронной почты с отображением ошибки, если регулярное выражение неправильное и т. Д. Итак, я создам «EmailWidget» и буду использовать его на двух экранах. Но если на третьем экране нужно ввести адрес электронной почты, но ошибки отображаются с другим текстом, я бы не дублировал весь виджет, просто переписал метод, показывающий ошибки. - person Lyofen; 29.11.2019
comment
В этом случае мне нужен общий виджет, но «общее состояние», безусловно, неправильный путь. Для других случаев мне нужно такое же состояние, но для некоторых виджетов с таким же поведением нужна дополнительная информация, поэтому я подумал о переопределении состояния без перезаписи всего виджета. - person Lyofen; 29.11.2019