Введение в поставщика и его использование (динамическая смена темы, контрпример, пример функциональности корзины и т. д.)

Типы управления состоянием во флаттере.

  • Провайдер
  • Речной стручок
  • setState
  • Унаследованный виджет и унаследованная модель
  • Редукс
  • Fish-Redux
  • БЛОК / Rx
  • Возьми
  • МобХ
  • Команды флаттера
  • связующее
  • ПолучитьX
  • States_rebuilder
  • Тройной шаблон (сегментированный шаблон состояния).

Что такое состояние во Flutter?

«Состояние» во Flutter относится к данным, хранящимся внутри виджета, которые можно изменять в зависимости от текущей операции. Состояние приложения может быть обновлено или полностью изменено при запуске приложения или при перезагрузке страницы.

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

Что такое Провайдер?

Пакет Provider, созданный Реми Русселе, направлен на максимально чистую обработку состояния. В Provider виджеты прослушивают изменения в состоянии и обновляются, как только получают уведомление.

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

Управление состоянием с помощью Provider

Вспомните, что мы обсуждали ранее о Provider: виджеты слушают изменения и уведомляют друг друга, если происходит перестроение. Как только состояние изменяется, этот конкретный виджет перестраивается, не затрагивая другие виджеты в дереве.

Все это возможно благодаря трем основным компонентам: классу ChangeNotifier во Flutter, классу ChangeNotifierProvider (в основном используемому в нашем примере приложения) и виджетам Consumer.

Любое изменение состояния, наблюдаемое в классе ChangeNotifier, вызывает перестроение виджета прослушивания. Пакет Provider предлагает различные типы провайдеров — некоторые из них перечислены ниже:

  • Provider класс принимает значение и предоставляет его независимо от типа значения.
  • ListenableProvider — это конкретный провайдер, используемый для прослушиваемых объектов. Он будет прослушивать, а затем запрашивать виджеты, зависящие от него и затронутые изменением состояния, для перестроения каждый раз, когда вызывается прослушиватель.
  • ChangeNotifierProvider похож на ListenableProvider, но для ChangeNotifier объектов и автоматически вызывает ChangeNotifier.dispose при необходимости
  • ValueListenableProvider слушает ValueListenable и показывает значение
  • StreamProvider прослушивает поток, показывает последнее сгенерированное значение и запрашивает виджеты, зависящие от потока, для перестроения
  • FutureProvider берет класс Future и обновляет виджеты в зависимости от него, когда будущее завершено
  • consumer виджет пакета поставщика, который реагирует на изменения ChangeNotifier и вызывает методы сборки для применения обновлений модели. перестроен. Вполне возможно, что 50% пользовательского интерфейса любого экрана, не в нашем случае, не нужно перестраивать. Таким образом, Consumer, который является виджетом, позволяет вам наблюдать за изменениями состояния от ChangeNotifier в определенной части пользовательского интерфейса, и, таким образом, будет повторно отображаться только наблюдаемая часть пользовательского интерфейса.

Давайте посмотрим, как мы можем реализовать Потребителя в провайдере.

Чтение значения с помощью следующих методов расширения

  1. context.watch‹T›() заставляет виджет прослушивать изменения в T.
  2. context.read‹T›(), который возвращает T, не слушая его
  3. Селектор context.select‹T, R› позволяет вам выбрать конкретное значение в провайдере для прослушивания. Затем, когда и только когда это выбранное значение изменится, виджет, возвращаемый методом построителя Selector, будет перестроен.

Также можно использовать статический метод Provider.of‹TaskProviders›(context), который будет вести себя аналогично watch.

Когда для параметра прослушивания установлено значение false (как в Provider.of‹TaskProviders›(context, listen: false)), то оно будет вести себя аналогично чтению.

Стоит отметить, что context.read‹T›() не вызывает перестроение виджета при изменении значения и не может вызываться внутри StatelessWidget.build/State.build. С другой стороны, его можно свободно вызывать вне этих методов.

Давайте посмотрим, как мы можем реализовать описанные выше методы в поставщике.

Прокси-провайдер

ProxyProvider — это провайдер, который объединяет несколько значений от других провайдеров в новый объект, а затем отправляет результат провайдеру. Он в основном вводит одно измененное значение в другого поставщика. Всякий раз, когда используется более одного провайдера и значение одного провайдера зависит от другого провайдера, мы используем ProxyProvider. Другой провайдер обновляет свое значение всякий раз, когда один из провайдеров, от которого он зависит, также обновляет.

то есть: у нас есть два провайдера: Person и Job. Для инициализации задания требуется человек. В этой ситуации задание является прокси. Это означает, что Job — это объект, с которым вы, вероятно, захотите взаимодействовать, но его значения зависят от Person.

Давайте посмотрим, как мы можем реализовать прокси-провайдера.

Будущий поставщик:

Как следует из названия, FutureProvider предоставляет будущее значение, которое может быть не готово, когда виджет, который получает значение, уже готов к использованию. И это во многом связано с классом Future во Flutter.

Это большое отличие от других провайдеров. Поскольку для появления предоставленного значения может потребоваться время, оно не должно быть нулевым. Вот почему у FutureProvider есть обязательный параметр "initial data", который представляет собой начальное значение, которое виджет может использовать до тех пор, пока не получит надлежащее предоставленное значение. Как только данные будут готовы, FutureProvider связывается с виджетом-потомком, чтобы перестроить и использовать новое значение.

Начиная

Начните с обычного примера счетчика.

Начните с создания нового проекта и добавьте эту строку в блок зависимостей в файле pubspec.yaml: provider

dependencies:
 provider: Letest dependencies

Запустите команду pub get, чтобы получить локальную копию пакета:

flutter pub get

Создайте класс поставщика, расширяющий «ChangeNotifier».

class CounterProvider(Your Class Name) extends ChangeNotifier {}

Добавьте логику для вашего кода

class CounterProvider(Your Class Name) extends ChangeNotifier {
int _count = 0;
int get getCountValue => _count;
//for Increment counter
void incrementCounter() {
     _count++;
     notifyListeners();
  }
//for Decrement counter
void decrementCounter() {
    _count--;
    notifyListeners();
}
//for reset counter
void resetCounter() {
    _count = 0;
    notifyListeners();
 }
}

Что делает notifyListeners во Flutter?

Метод notifyListeners Нулевая безопасность

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

Добавить провайдера в файл main.dart

void main() {
runApp(
MultiProvider(
 providers: [
  ChangeNotifierProvider(
    create: (context) => CounterProvider(),
  ),
  ChangeNotifierProvider(
    create: (context) => TimerInfo(),
  ),
  ChangeNotifierProvider(
    create: (context) => SalaryProvider(),
  ),
  ChangeNotifierProvider(
    create: (context) => ThemeProvider(),
  ),
  ChangeNotifierProvider(
    create: (context) => ItemProvider(),
  ),
 ],
    child: MyApp(),
   ),
 );
}

Получение данных из класса Provider.

class CounterScreen extends StatefulWidget {
const CounterScreen({Key? key}) : super(key: key);
@override
_CounterScreenState createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
@override
Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(),
  body: SafeArea(
   child: Center(
     child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer<CounterProvider>(
              builder: (context, value, child) {
                return Text(
                  value.getCountValue.toString(),
                  style: TextStyle(fontSize: 30),
                );
              },
           ),
      ],
    ),
  ),
),
floatingActionButton:  FloatingActionButton(
     onPressed: () {
      context.read<CounterProvider>().incrementCounter();
       },
      child: Icon(Icons.add),
     ), 
   );
 }
}

Получить исходный код из репозитория GitHub: Исходный код

нажмите Больше обновлений.