Anul trecut, am preluat Flutură și trebuie să spun că a fost o călătorie minunată până acum. Flutter este cadrul minunat al Google pentru crearea de aplicații de înaltă calitate pentru Android și iOS.

Ca și în cazul construirii a aproape orice aplicație, este întotdeauna necesară gestionarea stării aplicației. Este important ca gestionarea statului să fie gestionată eficient, pentru a evita acumularea de datorii tehnice, mai ales pe măsură ce aplicația dvs. crește și devine mai complexă.

În Flutter, toate componentele UI sunt widget-uri. Pe măsură ce începeți să compuneți aceste widget-uri pentru a vă crea aplicația minunată, veți ajunge cu un arbore de widget-uri adânc imbricate. Aceste widget-uri vor trebui cel mai probabil să partajeze starea aplicației între ele.

În acest articol, vom vedea cum să gestionăm starea în Flutter folosind modelul BLoC.

Managementul de stat în Flutter poate fi realizat în câteva moduri diferite:

Widget moștenit: Vă permite să propagați datele către widget-urile sale copil, iar widget-urile sunt reconstruite ori de câte ori există o modificare a stării aplicației. Dezavantajul utilizării clasei de bază InheritedWidget este că starea dvs. este finală și acest lucru ridică o problemă dacă doriți să vă mutați starea.

Model Scoped: Acesta este un pachet extern construit deasupra InheritedWidget și oferă un mod puțin mai bun de a accesa, actualiza și muta starea. Vă permite să treceți cu ușurință un model de date de la un widget părinte la descendenții săi. În plus, reconstruiește, de asemenea, toți copiii care folosesc modelul atunci când modelul este actualizat.

Acest lucru ar putea ridica o problemă de performanță, în funcție de câți ScopedModelDescendants are un model, deoarece sunt reconstruiți atunci când există o actualizare.

Această problemă poate fi rezolvată prin descompunerea ScopedModel în mai multe modele, astfel încât să obțineți dependențe mai fine. Setarea rebuildOnChange steag la false de asemenea, remediază această problemă, dar aduce cu sine sarcina cognitivă de a decide ce widget ar trebui să fie reconstruit sau nu.

Redux: Da! Ca și în React, există un pachet Redux care vă ajută să creați și să consumați cu ușurință un magazin Redux în Flutter. La fel ca omologul său JavaScript, există, de obicei, câteva linii de cod boilerplate și călătoria dus-întors acțiuni și reductoare.

Introduceți modelul BLoC

Modelul Business Logic Component (BLoC) este un model creat de Google și anunțat la Google I / O ’18. Modelul BLoC utilizează Programare reactivă pentru a gestiona fluxul de date dintr-o aplicație.

Un BLoC este un intermediar între o sursă de date din aplicația dvs. (de exemplu, un răspuns API) și widget-uri care au nevoie de date. Primește fluxuri de evenimente / date de la sursă, gestionează orice logică de afaceri necesară și publică fluxuri de modificări de date în widget-uri care sunt interesate de acestea.

Un BLoC are două componente simple: Chiuvete și Fluxuri, ambele fiind furnizate de un StreamController. Adăugați fluxuri de evenimente / date de intrare într-un Chiuvetă și ascultați-le ca fluxuri de date de ieșire printr-un Curent.

A StreamController poate fi accesat prin ‘dart:async’ bibliotecă sau ca PublishSubject, ReplaySubject sau ComportamentSubiect prin intermediul rxdart pachet.

Mai jos este un fragment de cod care arată un BLoC simplu:

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
  );
}
...

Un BLoC este o clasă simplă Dart. În fragmentul de cod de mai sus, am creat un CounterBloc clasa și în ea, a StreamController pe care am numit-o counterController. Am creat un getter pentru fluxul nostru numit getCount, un updateCount metodă care adaugă date în chiuveta noastră atunci când este apelat și a dispose metoda de închidere a StreamController-ului nostru.

Pentru a accesa datele din fluxul nostru, am creat un StreamBuilder widget și a transmis fluxul nostru către stream proprietate și a accesat datele din builder funcţie.

Implementarea BLoC

Vom converti aplicația eșantion implicită Flutter pentru a utiliza un BLoC. Să mergem mai departe și să generăm o nouă aplicație Flutter. În terminalul dvs. executați următoarea comandă:

$ flutter create bloc_counter && cd bloc_counter

Deschideți aplicația în editorul preferat și creați trei fișiere în folderul lib: counter.dart, counter_provider.dart și counter_bloc.dart.

Al nostru CounterProvider va conține un număr întreg și o metodă pentru incrementarea acestuia. Adăugați următorul cod la counter_provider.dart fişier:

class CounterProvider {
  int count = 0;
  void increaseCount() => count++;
}

Apoi, vom implementa contorul nostru BLoC. Adăugați codul de mai jos în counter_block.dart fişier:

În a noastră CounterBloc clasă, am folosit o parte din eșantionul de cod inițial de mai sus. Pe linia 7, ne-am instanțiat CounterProvider clasa și în updateCount , am apelat metoda furnizorului pentru a crește numărul și apoi pe linia 13, am trecut numărul la chiuveta noastră.

Înlocuiți codul din main.dart fișier cu codul de mai jos. În codul de mai jos, am eliminat pur și simplu majoritatea codului implicit al contorului, pe care îl vom muta la al nostru counter.dart fişier. Ori de câte ori incrementCounter se numește metoda, numim BLoC updateCount metodă care actualizează numărul și îl adaugă la Sink.

Acum, BLoC-ul nostru primește și transmite date. Putem accesa aceste date și le putem afișa pe un ecran printr-un StreamBuilder. Înfășurăm orice widget care are nevoie de date într-un widget StreamBuilder și îi transmitem fluxul care conține datele. Adăugați următorul cod la counter.dart fişier:

În codul de mai sus, avem un widget cu stare. În clasa noastră de stat, pe linia 13, numim metoda de eliminare a blocului nostru, astfel încât controlerul de flux poate fi închis ori de câte ori widgetul este eliminat din copac.

Pe linia 19, returnăm un widget StreamBuilder și linia 20, trecem getter-ul pentru fluxul nostru către acesta și, de asemenea, o dată inițială pe linia 21. StreamBuilder are, de asemenea, un builder care ne oferă acces la date prin intermediul unui snapshot. Pe linia 30, accesăm și afișăm datele în instantaneu.

Mergeți mai departe și rulați aplicația executând comanda de mai jos. Asigurați-vă că aveți un emulator care rulează.

$ flutter run

Când aplicația rulează, faceți clic pe pictograma plus și urmăriți contorul crescând la fiecare clic.

Cum sa gestionati starea in Flutter folosind modelul BLoC
aplicație demonstrativă

Împreună, am reușit să implementăm cea mai simplă formă de BLoC în Flutter. Conceptul rămâne același indiferent de cazul dvs. de utilizare.

Sper că ți s-a părut util acest articol. Vă rugăm să faceți și să partajați pentru ca alții să poată găsi acest articol. Luați-mă pe Twitter @developia_ cu întrebări sau pentru un chat.