Hallo an alle! In diesem Artikel möchte ich Ihnen zeigen, wie Sie mit Redux eine Flutter-Anwendung erstellen. Wenn Sie nicht wissen, was
Flutter ist , handelt es sich um ein Open-Source-SDK zum Erstellen mobiler Anwendungen von Google. Es wird zum Entwickeln von Anwendungen für Android und iOS verwendet und ist auch die einzige Möglichkeit, Anwendungen für Google Fuchsia zu entwickeln.
Wenn Sie mit Flutter vertraut sind und eine Anwendung erstellen möchten, die gut gestaltet, einfach zu testen und ein vorhersehbares Verhalten aufweist, lesen Sie diesen Artikel weiter und Sie werden es bald herausfinden!
Aber bevor wir anfangen, die Anwendung selbst zu schreiben. Machen wir uns ein wenig mit der Theorie vertraut und erklären wir zunächst, was Redux ist.
Was ist Redux?
Redux ist eine Architektur, die ursprünglich für die JavaScript-Sprache erstellt wurde und in Anwendungen verwendet wird, die mit
reaktiven Frameworks (z. B. React Native oder Flutter) erstellt wurden. Redux ist eine vereinfachte Version der von Facebook erstellten Flux-Architektur. Im Wesentlichen müssen Sie drei Dinge wissen:
- Die einzige Quelle der Wahrheit - der gesamte Status Ihrer Anwendung wird an nur einem Ort gespeichert ( Store genannt ).
- state ist schreibgeschützt / state ist schreibgeschützt - um den Status der Anwendung zu ändern, müssen Sie Aktionen (action) senden, nach denen ein neuer Status erstellt wird
- Änderungen werden mit reinen Funktionen / reinen Funktionen vorgenommen - eine reine Funktion (der Einfachheit halber handelt es sich um eine Funktion ohne Nebenwirkungen) übernimmt den aktuellen Status der Anwendung und führt eine Aktion durch und gibt den neuen Status der Anwendung zurück
Hinweis: Ein Nebeneffekt der Funktion ist die Fähigkeit, bei der Ausführung ihrer Berechnungen die Werte globaler Variablen zu lesen und zu ändern, E / A-Operationen auszuführen, auf Ausnahmesituationen zu reagieren und ihre Handler aufzurufen. Wenn Sie eine Funktion mit einem Nebeneffekt zweimal mit demselben Satz von Eingabeargumentwerten aufrufen, kann es vorkommen, dass als Ergebnis unterschiedliche Werte zurückgegeben werden. Solche Funktionen werden als nicht deterministische Funktionen mit Nebenwirkungen bezeichnet.Klingt cool, aber was sind die Vorteile dieser Lösung?
- Wir haben die Kontrolle über Zustand / Zustand - das bedeutet, wir wissen genau, was die Zustandsänderung verursacht hat, wir haben keinen doppelten Zustand und wir können den Datenfluss leicht überwachen
- Reduzierer sind reine Funktionen, die einfach zu testen sind - wir können den Status und die Aktion an den Eingang übergeben und prüfen, ob das Ergebnis wahr ist
- Die Anwendung ist klar strukturiert - wir haben verschiedene Ebenen für Aktionen, Modelle, Geschäftslogik usw. - damit Sie genau wissen, wo Sie eine weitere neue Funktion hinzufügen können
- Es ist eine großartige Architektur für komplexere Anwendungen. Sie müssen den Status nicht über den gesamten Strukturbaum Ihrer Ansicht von Eltern zu Kindern weitergeben
- und da ist noch einer ...
Redux Zeitreise
Redux hat eine interessante Gelegenheit - Zeitreisen! Mit Redux und verwandten Tools können Sie den Status Ihrer Anwendung über einen längeren Zeitraum verfolgen, den aktuellen Status überprüfen und jederzeit neu erstellen. Sehen Sie diese Funktion in Aktion:
Redux-Widgets mit einem einfachen Beispiel
Alle oben genannten Regeln bewirken, dass der Datenfluss in Redux unidirektional erfolgt. Aber was heißt das? In der Praxis geschieht dies alles mit
Aktionen ,
Reduzierungen ,
Speichern und
Zuständen . Stellen wir uns eine Anwendung vor, die einen Zähler anzeigt:
- Ihre Anwendung hat beim Start einen bestimmten Status (die Anzahl der Klicks, die 0 ist)
- Basierend auf diesem Status wird die Ansicht gerendert.
- Wenn der Benutzer auf die Schaltfläche klickt, wird die Aktion gesendet (z. B. IncrementCounter).
- Danach erhält die Aktion einen Reduzierer , der den vorherigen Status kennt (Zähler 0), und erhält eine Aktion (IncrementCounter) und kann einen neuen Status zurückgeben (der Zähler ist jetzt 1).
- Unsere Anwendung hat einen neuen Status (Zähler ist 1)
- Basierend auf dem neuen Status wird die Ansicht neu gezeichnet, wodurch der aktuelle Status angezeigt wird
Wie Sie sehen, geht es in der Regel nur um den
Status . Sie haben einen Status der gesamten Anwendung, der
Status ist schreibgeschützt , und um einen neuen
Status zu erstellen, müssen Sie eine
Aktion senden. Durch das Senden von
Aktionen wird ein
Reduzierer gestartet, der einen neuen
Status erstellt und an uns zurückgibt. Und die Geschichte wiederholt sich.
Lassen Sie uns eine kleine Anwendung erstellen und die Umsetzung des Redux-Ansatzes in Aktion kennenlernen. Die Anwendung wird als "
Einkaufsliste " bezeichnet.
Wir werden sehen, wie Redux in der Praxis funktioniert. Wir erstellen eine einfache ShoppingCart-App. Die Anwendung verfügt über Funktionen wie:
- Käufe hinzufügen
- Der Kauf kann als abgeschlossen markiert werden
- und das ist im Grunde alles
Die Anwendung sieht folgendermaßen aus:
Beginnen wir mit dem Schreiben von Code!
Voraussetzung
In diesem Artikel werde ich die Erstellung der Benutzeroberfläche für diese Anwendung nicht zeigen.
Sie können sich mit dem Code vertraut machen, den ich für Sie vorbereitet habe, bevor Sie mit dem Redux-Tauchgang fortfahren . Danach werden wir weiter Code schreiben und
Redux zur aktuellen Anwendung hinzufügen.
Hinweis: Wenn Sie Flutter noch nie zuvor verwendet haben, empfehlen wir Ihnen, Flutter Codelabs von Google zu verwenden .Vorbereitende Vorbereitung
Um
Redux for Flutter verwenden zu können, müssen Abhängigkeiten zur Datei
pubspec.yaml hinzugefügt werden:
flutter_redux: ^0.5.2
Sie können auch die aktuelle Version dieser Abhängigkeit überprüfen, indem Sie auf die Seite
flutter_redux gehen .
Zum Zeitpunkt des Schreibens war die Version flutter_redux 0.6.0Modell
Unsere Anwendung sollte in der Lage sein, das Hinzufügen und Ändern von Elementen zu steuern.
Daher verwenden wir ein einfaches
CartItem- Modell, um den Status eines Elements zu speichern. Alle unsere Anwendungsstatus sind nur eine Liste von CartItems. Wie Sie sehen, ist CartItem nur ein Objekt.
class CartItem { String name; bool checked; CartItem(this.name, this.checked); }
Zuerst müssen wir Aktionen deklarieren. Aktion ist in der Tat jede Absicht, die aufgerufen werden kann, um den Status einer Anwendung zu ändern. Im Wesentlichen gibt es zwei Aktionen zum Hinzufügen und Ändern eines Elements:
class AddItemAction { final CartItem item; AddItemAction(this.item); } class ToggleItemStateAction { final CartItem item; ToggleItemStateAction(this.item); }
Dann müssen wir unserer Anwendung mitteilen, was mit diesen
Aktionen geschehen soll . Aus diesem Grund werden
Reduzierungen verwendet. Sie übernehmen nur den aktuellen Status der Anwendung und der Aktion (Anwendungsstatus und Aktion) und erstellen dann einen neuen Status und geben ihn zurück. Wir werden zwei
Reduzierungsmethoden haben :
List<CartItem> appReducers(List<CartItem> items, dynamic action) { if (action is AddItemAction) { return addItem(items, action); } else if (action is ToggleItemStateAction) { return toggleItemState(items, action); } return items; } List<CartItem> addItem(List<CartItem> items, AddItemAction action) { return List.from(items)..add(action.item); } List<CartItem> toggleItemState(List<CartItem> items, ToggleItemStateAction action) { return items.map((item) => item.name == action.item.name ? action.item : item).toList(); }
Die
appReducers () -Methode delegiert die Aktion an die entsprechenden Methoden. Die
Methoden addItem () und
toggleItemState () geben neue Listen zurück - dies ist unser neuer Zustand. Wie Sie sehen,
sollten Sie
die aktuelle Liste nicht ändern . Stattdessen erstellen wir jedes Mal eine neue Liste.
StoreProvider
Nachdem wir nun
Aktionen und
Reduzierungen haben , müssen wir einen Speicherort für den
Status der Anwendung bereitstellen . In Redux heißt es
store und ist die einzige Quelle der Wahrheit für die Anwendung.
void main() { final store = new Store<List<CartItem>>( appReducers, initialState: new List()); runApp(new FlutterReduxApp(store)); }
Um ein
Geschäft zu erstellen, müssen wir die
Reduktionsmethode und den Anfangszustand übergeben. Wenn wir ein
Geschäft erstellt haben , müssen wir es an
StoreProvider übergeben , um unserer Anwendung mitzuteilen, dass das
Geschäft von jedem verwendet werden kann, der den aktuellen
Status der Anwendung anfordern möchte.
class FlutterReduxApp extends StatelessWidget { final Store<List<CartItem>> store; FlutterReduxApp(this.store); @override Widget build(BuildContext context) { return new StoreProvider<List<CartItem>>( store: store, child: new ShoppingCartApp(), ); } }
Im obigen Beispiel ist
ShoppingCartApp ( ) das Hauptwidget unserer Anwendung.
StoreConnector
Wir haben derzeit alles außer ... das Hinzufügen und Ändern von Artikeln zum Kauf. Wie kann man das machen? Um dies zu ermöglichen, müssen wir den
StoreConnector verwenden . Auf diese Weise können Sie den
Speicher abrufen und ihm eine
Aktion senden oder einfach den aktuellen
Status abrufen .
Zunächst möchten wir die aktuellen Daten abrufen und als Liste auf dem Bildschirm anzeigen:
class ShoppingList extends StatelessWidget { @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, List<CartItem>>( converter: (store) => store.state, builder: (context, list) { return new ListView.builder( itemCount: list.length, itemBuilder: (context, position) => new ShoppingListItem(list[position])); }, ); } }
Der obige Code
umschließt ListView.builder mit einem
StoreConnector .
StoreConnector kann den aktuellen
Status (eine Liste von Elementen
) akzeptieren
und mithilfe von Kartenfunktionen in alles konvertieren. In unserem Fall ist es jedoch derselbe Status (Liste), da wir hier eine Einkaufsliste benötigen.
Als Nächstes erhalten wir in der Builder- Funktion eine Liste - im Grunde genommen eine Liste der CartItems aus dem Store , mit denen wir eine ListView erstellen können .
Ok, cool - wir haben Daten. Nun, wie man einige Daten einstellt?
Dafür verwenden wir auch den StoreConnector , allerdings auf etwas andere Weise.
class AddItemDialog extends StatelessWidget { @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, OnItemAddedCallback>( converter: (store) { return (itemName) => store.dispatch(AddItemAction(CartItem(itemName, false))); }, builder: (context, callback) { return new AddItemDialogWidget(callback); }); } }typedef OnItemAddedCallback = Function(String itemName);
Schauen wir uns den Code an. Wir haben den StoreConnector wie im vorherigen Beispiel verwendet, aber dieses Mal werden wir, anstatt die CartItems- Liste mit derselben Liste abzugleichen , eine Zuordnungskonvertierung in OnItemAddedCallback durchführen . Daher können wir die Rückruffunktion an AddItemDialogWidget übergeben und sie aufrufen, wenn der Benutzer ein neues Element hinzufügt :
class AddItemDialogWidgetState extends State<AddItemDialogWidget> { String itemName; final OnItemAddedCallback callback; AddItemDialogWidgetState(this.callback); @override Widget build(BuildContext context) { return new AlertDialog( ... actions: <Widget>[ ... new FlatButton( child: const Text('ADD'), onPressed: () { ... callback(itemName); }) ], ); } }
Jedes Mal, wenn der Benutzer auf die Schaltfläche HINZUFÜGEN klickt, sendet die Rückruffunktion eine Aktion AddItemAction () .
Jetzt können wir eine sehr ähnliche Implementierung zum Ändern des Zustands eines Elements vornehmen.
class ShoppingListItem extends StatelessWidget { final CartItem item; ShoppingListItem(this.item); @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, OnStateChanged>( converter: (store) { return (item) => store.dispatch(ToggleItemStateAction(item)); }, builder: (context, callback) { return new ListTile( title: new Text(item.name), leading: new Checkbox( value: item.checked, onChanged: (bool newValue) { callback(CartItem(item.name, newValue)); }), ); }); } }
Wie im vorherigen Beispiel verwenden wir den StoreConnector , um die Liste für die OnStateChanged- Rückruffunktion anzuzeigen . Jedes Mal, wenn sich das Flag ändert (in der onChanged-Methode), löst die Rückruffunktion das ToggleItemStateAction- Ereignis aus.
Zusammenfassung
Das ist alles! In diesem Artikel haben wir eine einfache Anwendung erstellt, die eine Einkaufsliste anzeigt und ein wenig in die Verwendung der Redux-Architektur eintaucht. In unserer Anwendung können wir Elemente hinzufügen und deren Status ändern. Das Hinzufügen neuer Funktionen zu dieser Anwendung ist so einfach wie das Hinzufügen neuer Aktionen und Reduzierungen .
Hier finden Sie den Quellcode dieser Anwendung, einschließlich des Zeitreise- Widgets:
Hoffe dir hat dieser Beitrag gefallen!