RxDart für die kleinsten ... Projekte


Gestern sagte mein guter Freund etwas wie "Ich schreibe eine einfache Offline-Anwendung, ich brauche nicht alle diese Streams und Streams." Ich war sogar verblüfft und dachte dann, dass andere Encoder diesen Fehler teilen könnten.


Im Folgenden werde ich buchstäblich in 50 Zeilen anhand eines bekannten Beispiels die Reaktivität zeigen


a) es geht nicht um offline / online
b) es ist sehr einfach
c) sehr gut für die Vereinfachung von fast jedem Code


An meine überstürzten Kritiker
Wer ohne nachzudenken in die Schlacht BlocProvider , da BlocProvider ein Anbieter ist , dem empfehle ich, für die allgemeine Entwicklung zunächst den BlocProvider zu lesen, auf den auf der Seite flutter_bloc in der ersten Zeile der Beschreibung verwiesen wird.


Das bekannte Beispiel "Counter", das beim Erstellen eines Flutter-Projekts generiert wird, ist peitschender Junge Ein guter Ausgangspunkt, um viele Praktiken zu demonstrieren.
Daher enthält MyHomePage extends StatefulWidget die _incrementCounter MyHomePage extends StatefulWidget , die _incrementCounter Methode für den Befehl increment und setState , um die gesamte Widget-Hierarchie neu zu zeichnen.


Wir führen die Reaktivität mit der rxdart Bibliothek und ein paar einfachen Schritten ein:


Fügen Sie die Bibliothek pubspec.yaml hinzu


 dependencies: ... rxdart: 0.22.2 

Ändern Sie die Zählerarchitektur und fügen Sie ein Ereignis hinzu


 class _Counter { int _count; int get count => _count; _Counter(this._count) : this.onCounterUpd = BehaviorSubject<int>.seeded(_count); ///  . final BehaviorSubject<int> onCounterUpd; ///     ,   . Future incrementCounter() async { onCounterUpd.add(++_count); } } final _counter = _Counter(5); 

Machen wir die Klasse StatelessWidget


 ///   " " class MyHomeRxPage extends StatelessWidget { final title; /// ! -     const MyHomeRxPage({Key key, this.title}) : super(key: key); ... 

Schließen Sie das Anzeige-Widget in StreamBuilder ein und ändern Sie den Aufruf in die Methode increment


  StreamBuilder<int>( stream: _counter.onCounterUpd, builder: (context, snapshot) { return Text( '${snapshot.data}', style: Theme.of(context).textTheme.display1, ); }), ... floatingActionButton: FloatingActionButton( onPressed: _counter.incrementCounter, ... 

Das ist alles. Es sieht total so aus


 import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:rxdart/rxdart.dart'; class _Counter { int _count; int get count => _count; _Counter(this._count) : this.onCounterUpd = BehaviorSubject<int>.seeded(_count); ///  . final BehaviorSubject<int> onCounterUpd; ///     ,   . Future incrementCounter() async { onCounterUpd.add(++_count); } } final _counter = _Counter(5); /// class MyHomeRxPage extends StatelessWidget { final title; /// ! -     const MyHomeRxPage({Key key, this.title}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. title: Text(title), ), body: Center( // Center is a layout widget. It takes a single child and positions it // in the middle of the parent. child: Column( // Column is also a layout widget. It takes a list of children and // arranges them vertically. By default, it sizes itself to fit its // children horizontally, and tries to be as tall as its parent. // // Invoke "debug painting" (press "p" in the console, choose the // "Toggle Debug Paint" action from the Flutter Inspector in Android // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) // to see the wireframe for each widget. // // Column has various properties to control how it sizes itself and // how it positions its children. Here we use mainAxisAlignment to // center the children vertically; the main axis here is the vertical // axis because Columns are vertical (the cross axis would be // horizontal). mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ StreamBuilder<int>( stream: _counter.onCounterUpd, builder: (context, snapshot) { return Text( 'You have pushed the button ${snapshot.data} times:', ); }), // Text( // 'You have pushed the button this many times:', // ), /// 6. StreamBuilder<int>( stream: _counter.onCounterUpd, builder: (context, snapshot) { return Text( '${snapshot.data}', style: Theme.of(context).textTheme.display1, ); }), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _counter.incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } } 

Jetzt ist der Code reaktiv, übersichtlich, frei von unnötigen Neuzeichnungen und leicht erweiterbar.
Wenn Sie beispielsweise zum Zeitpunkt der Änderung des Zählers den Text eines anderen Widgets ändern müssen, gehen Sie wie folgt vor:


  StreamBuilder<int>( stream: onCounterUpd, builder: (context, snapshot) { return Text( 'You have pushed the button ${snapshot.data} times:', ); }), // Text( // 'You have pushed the button this many times:', // ), 

und voila!


Versuchen Sie zum Vergleich, dasselbe mit InheritedWidget oder einem anderen Muster zu tun.


Hoffentlich habe ich das gezeigt


  • Reaktivität ist sehr einfach. Viel einfacher InheritedWidgets , BlocProvider usw.
  • Bei Reaktivität geht es nicht um Offline / Online. Sie handelt von Architektur. Wie ich gezeigt habe, müssen Sie in den einfachsten Fällen nicht einmal zusätzliche Klassen hinzufügen, um sie anzuwenden.
  • Reaktivität ist reaktionsschnelle Benutzeroberflächen, schnelle Funktionserweiterung und ordnungsgemäße Aufteilung des Codes in beliebige Ebenen: MVC, MVP, MVI, MVVM, was immer Sie möchten.

Beispielcode (Zweig iter_0004_rxdart )


Eine Stunde später bearbeitet
Vergebens zu einfach, bekam Klicks für "globale Variablen" und ein falsches Verständnis der BehaviorSubject Initialisierung, behoben

Source: https://habr.com/ru/post/de474968/


All Articles