Минулого року я взяв Флаттера, і мушу сказати, що поки що це була надзвичайна подорож. Flutter - це чудова платформа Google для створення високоякісних додатків для Android та iOS.
Як і при побудові майже будь-якої програми, завжди існує необхідність обробляти стан програми. Важливо, щоб управління державою здійснювалося ефективно, щоб уникнути накопичення технічної заборгованості, особливо в міру того, як ваша заявка зростає та ускладнюється.
У Flutter всі компоненти інтерфейсу є віджетами. Починаючи складати ці віджети, щоб створити свою чудову програму, у вас з’явиться дерево глибоко вкладених віджетів. Ці віджети, швидше за все, потребуватимуть обміну станом програми між собою.
У цій статті ми побачимо, як обробляти стан у Flutter за допомогою шаблону BLoC.
Управління державою в Flutter можна досягти кількома різними способами:
Успадкований віджет : він дозволяє розповсюджувати дані до своїх дочірніх віджетів, і віджети відновлюються щоразу, коли змінюється стан програми. Недоліком використання базового класу InheritedWidget є те, що ваш стан остаточний, і це створює проблему, якщо ви хочете змінити свій стан.
Модель із розмахом : це зовнішній пакет, побудований поверх InheritedWidget, і він пропонує дещо кращий спосіб отримати доступ, оновити та змінити стан. Це дозволяє легко передавати Модель даних від батьківського віджету до його нащадків. Крім того, він також перебудовує всіх дітей, які використовують модель, коли модель оновлюється.
Це може спричинити проблему продуктивності, залежно від того, скільки ScopedModelDescendants має модель, оскільки вони відновлюються при оновленні.
Цю проблему можна виправити, розклавши ScopedModel на кілька моделей, щоб отримати детальніші залежності. Встановлення rebuildOnChange
прапора false
також виправляє цю проблему, але це приносить із собою пізнавальне навантаження щодо вирішення, який віджет слід відновити чи ні.
Redux : Так! Як і у випадку з React, існує пакет Redux, який допоможе вам легко створити та використати магазин Redux у Flutter. Як і його аналог JavaScript, зазвичай є кілька рядків зразкового коду та зворотній шлях дій та редукторів .
Введіть шаблон BLoC
Шаблон Business Logic Component (BLoC) - це шаблон, створений Google і оголошений на Google I / O '18. Шаблон BLoC використовує реактивне програмування для обробки потоку даних у програмі.
BLoC є посередником між джерелом даних у вашому додатку (наприклад, відповідь API) та віджетами, які потребують даних. Він отримує потоки подій / даних від джерела, обробляє будь-яку необхідну бізнес-логіку та публікує потоки змін даних у віджетах, які їх цікавлять.
BLoC має два простих компоненти: Мийки та Потоки , обидва з яких забезпечуються StreamController . Ви додаєте потоки подій / даних, що вводяться в раковину, і слухаєте їх як потоки даних, що виводяться через потік .
StreamController можна отримати доступ через ‘dart:async’
бібліотеку або як PublishSubject , ReplaySubject або BehaviourSubject через rxdart
пакет.
Нижче наведено фрагмент коду, що показує простий BLoC:
import 'dart:async'; // import 'package:rxdart/rxdart.dart'; if you want to make use of PublishSubject, ReplaySubject or BehaviourSubject. // make sure you have rxdart: as a dependency in your pubspec.yaml file to use the above import class CounterBloc { final counterController = StreamController(); // create a StreamController or // final counterController = PublishSubject() or any other rxdart option; Stream get getCount => counterController.stream; // create a getter for our Stream // the rxdart stream controllers returns an Observable instead of a Stream void updateCount() { counterController.sink.add(data); // add whatever data we want into the Sink } void dispose() { counterController.close(); // close our StreamController to avoid memory leak } } final bloc = CounterBloc(); // create an instance of the counter bloc //======= end of CounterBloc file //======= somewhere else in our app import 'counter_bloc.dart'; // import the counter bloc file here @override void dispose() { bloc.dispose(); // call the dispose method to close our StreamController super.dispose(); } ... @override Widget build(BuildContext context) { return StreamBuilder( // Wrap our widget with a StreamBuilder stream: bloc.getCount, // pass our Stream getter here initialData: 0, // provide an initial data builder: (context, snapshot) => Text('${snapshot.data}'), // access the data in our Stream here ); } ...
BLoC - це простий клас Dart. У наведеному вище фрагменті коду ми створили CounterBloc
клас і в ньому, StreamController
який ми викликали counterController
. Ми створили геттер для нашого потоку, який називається getCount
, updateCount
метод, який додає дані в нашу раковину при dispose
виклику , і метод, щоб закрити наш StreamController.
Щоб отримати доступ до даних у нашому потоці, ми створили StreamBuilder
віджет і передали наш потік до його stream
властивості та отримали доступ до даних у його builder
функції.
Впровадження BLoC
Ми перетворимо зразок програми Flutter за замовчуванням на використання BLoC. Давайте створимо новий додаток Flutter. У вашому терміналі запустіть таку команду:
$ flutter create bloc_counter && cd bloc_counter
Відкрийте додаток у вашому улюбленому редакторі і створити три файли в папці Lib: counter.dart
, counter_provider.dart
і counter_bloc.dart
.
Ми CounterProvider
міститиме ціле число та спосіб його збільшення. Додайте до counter_provider.dart
файлу такий код :
class CounterProvider { int count = 0; void increaseCount() => count++; }
Далі ми реалізуємо наш лічильник BLoC. Додайте код нижче у свій counter_block.dart
файл:
У нашому CounterBloc
класі ми використовували частину нашого початкового зразка коду вище. У рядку 7 ми створили інстанцію нашого CounterProvider
класу, а в updateCount
методі ми викликали метод провайдера для збільшення кількості, а потім у рядку 13 передали відлік в наш Sink.
Замініть код у вашому main.dart
файлі на код нижче. У наведеному нижче коді ми просто видалили більшу частину коду лічильника за замовчуванням, який ми перемістимо до нашого counter.dart
файлу. Щоразу, коли incrementCounter
метод викликається, ми викликаємо updateCount
метод BLoC, який оновлює рахунок і додає його до нашого Sink.
Зараз наш BLoC отримує та передає дані. Ми можемо отримати доступ до цих даних і відобразити їх на екрані через StreamBuilder . Ми обертаємо будь-який віджет, який потребує даних, у віджет StreamBuilder і передаємо йому потік, що містить дані. Додайте до counter.dart
файлу такий код :
У наведеному вище коді ми маємо віджет з виглядів. У нашому класі стану, у рядку 13, ми викликаємо метод dispose нашого блоку, так що контролер потоку може бути закритий при кожному видаленні віджета з дерева.
У рядку 19 ми повертаємо віджет StreamBuilder і рядок 20, передаємо йому геттер для нашого потоку, а також початкові дані в рядку 21. StreamBuilder також має такий, builder
який надає нам доступ до даних через snapshot
. У рядку 30 ми отримуємо доступ та відображаємо дані на знімку.
Вперед і запустіть програму, виконавши команду нижче. Переконайтеся, що у вас запущений емулятор.
$ flutter run
Коли ваш додаток запущений, натисніть значок плюса і спостерігайте, як лічильник збільшується з кожним клацанням.

Разом ми змогли реалізувати найпростішу форму BLoC у Flutter. Концепція залишається незмінною незалежно від вашого випадку використання.
Сподіваюся, ця стаття виявилася вам корисною. Будь ласка, робіть і діліться, щоб інші могли знайти цю статтю. Підкажіть мені у Twitter @developia_ з питаннями або для чату.