Sådan håndteres tilstand i Flutter ved hjælp af BLoC-mønster

Sidste år hentede jeg Flutter, og jeg må sige, at det hidtil har været en fantastisk rejse. Flutter er Googles fantastiske ramme til at skabe applikationer af høj kvalitet til Android og iOS.

Som med at bygge næsten enhver applikation er der altid behov for at håndtere applikationstilstand. Det er vigtigt, at statsadministration håndteres effektivt for at undgå at optjene teknisk gæld, især når din ansøgning vokser og bliver mere kompleks.

I Flutter er alle UI-komponenter widgets. Når du begynder at komponere disse widgets for at oprette din fantastiske app, ender du med et træ med dybt indlejrede widgets. Disse widgets skal sandsynligvis dele applikationstilstand med hinanden.

I denne artikel vil vi se, hvordan man håndterer tilstand i Flutter ved hjælp af BLoC-mønsteret.

Statsledelse i Flutter kan opnås på et par forskellige måder:

Arvet widget : Det giver dig mulighed for at formidle data til dets underordnede widgets, og widgets genopbygges, når der er en ændring i appens tilstand. Ulempen ved at bruge InheritedWidget-baseklassen er, at din tilstand er endelig, og dette rejser et problem, hvis du vil mutere din tilstand.

Scoped Model : Dette er en ekstern pakke bygget oven på InheritedWidget, og den giver en lidt bedre måde at få adgang til, opdatere og mutere tilstand. Det giver dig mulighed for let at overføre en datamodel fra en forældre-widget ned til dens efterkommere. Derudover genopbygger det også alle de børn, der bruger modellen, når modellen opdateres.

Dette kan muligvis rejse et præstationsproblem afhængigt af hvor mange ScopedModelDescendants en model har, da de genopbygges, når der er en opdatering.

Dette problem kan løses ved at nedbryde ScopedModel i flere modeller, så du får mere detaljerede afhængigheder. Indstilling af rebuildOnChangeflag til falseogså løser dette problem, men det bringer den kognitive belastning med at beslutte, hvilken widget der skal genopbygges eller ej.

Redux : Ja! Som med React er der en Redux-pakke, der hjælper dig med nemt at oprette og forbruge en Redux-butik i Flutter. Ligesom dets JavaScript-modstykke er der normalt et par linjer kedelpladekode og rundtur af handlinger og reduktionsmidler .

Indtast BLoC mønster

BLOC-mønsteret (Business Logic Component) er et mønster oprettet af Google og annonceret på Google I / O '18. BLoC-mønsteret bruger reaktiv programmering til at håndtere datastrømmen i en app.

En BLoC står som en mellemmand mellem en datakilde i din app (f.eks. Et API-svar) og widgets, der har brug for dataene. Den modtager strømme af begivenheder / data fra kilden, håndterer enhver krævet forretningslogik og offentliggør strømme af dataforandringer til widgets, der er interesseret i dem.

En BLoC har to enkle komponenter: Sinks og Streams , som begge leveres af en StreamController . Du tilføjer streams af hændelses- / datainput i et Sink og lytter til dem som streams af dataoutput gennem en Stream .

En StreamController kan tilgås via ‘dart:async’biblioteket eller som en PublishSubject , ReplaySubject eller BehaviourSubject via rxdartpakken.

Nedenfor er et kodestykke, der viser en simpel 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 ); } ...

En BLoC er en simpel Dart-klasse. I kodestykket ovenfor oprettede vi en CounterBlocklasse og i den, StreamControllersom vi kaldte counterController. Vi oprettede en getter til vores Stream kaldet getCount, en updateCountmetode, der tilføjer data til vores Sink, når den kaldes, og en disposemetode til at lukke vores StreamController.

For at få adgang til dataene i vores Stream oprettede vi en StreamBuilderwidget og sendte vores Stream til dens streamejendom og fik adgang til dataene i dens builderfunktion.

Implementering af BLoC

Vi konverterer standardflutter-prøveappen til at bruge en BLoC. Lad os gå videre og generere en ny Flutter-app. Kør følgende kommando i din terminal:

$ flutter create bloc_counter && cd bloc_counter

Åbn app i din favorit editor og oprette tre filer i lib mappe: counter.dart, counter_provider.dartog counter_bloc.dart.

Vores CounterProvidervil indeholde et heltal og en metode til at øge det. Tilføj følgende kode til counter_provider.dartfilen:

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

Dernæst implementerer vi vores counter BLoC. Tilføj nedenstående kode i din counter_block.dartfil:

I vores CounterBlocklasse brugte vi en del af vores oprindelige prøvekode ovenfor. På linje 7 instantierede vi vores CounterProviderklasse, og i updateCountmetoden kaldte vi udbydermetoden for at øge optællingen, og på linje 13 sendte vi optællingen til vores vask.

Udskift koden i din main.dartfil med koden nedenfor. I koden nedenfor fjernede vi simpelthen det meste af standardtællerkoden, som vi flytter til vores counter.dartfil. Når incrementCountermetoden kaldes, kalder vi BLoC- updateCountmetoden, som opdaterer optællingen og føjer den til vores vask.

Nu modtager og streamer vores BLoC data. Vi kan få adgang til disse data og vise dem på en skærm via en StreamBuilder . Vi indpakker den widget, der har brug for dataene, i en StreamBuilder-widget og sender strømmen, der indeholder dataene, til den. Tilføj følgende kode til counter.dartfilen:

I koden ovenfor har vi en stateful widget. I vores tilstandsklasse, på linje 13, kalder vi vores blok's bortskaffelsesmetode, så streamcontroller kan lukkes, når widgeten fjernes fra træet.

På linje 19 returnerer vi en StreamBuilder-widget og linje 20, vi sender getter til vores stream til den og også en indledende data på linje 21. StreamBuilder har også en, buildersom giver os adgang til dataene via en snapshot. På linje 30 får vi adgang til og viser dataene i øjebliksbillede.

Gå videre og kør appen ved at køre kommandoen nedenfor. Sørg for, at du kører en emulator.

$ flutter run

Når din app kører, skal du klikke på plusikonet og se tælleren stige med hvert klik.

Sammen har vi været i stand til at implementere den enkleste form for en BLoC i Flutter. Konceptet forbliver det samme uanset din brugssag.

Jeg håber, du fandt denne artikel nyttig. Venligst gør og del, så andre kan finde denne artikel. Slå mig op på Twitter @developia_ med spørgsmål eller til en chat.