Kürzlich wurde ich auf die Nachricht aufmerksam, dass die nächste
Version von Flutter (1.9) veröffentlicht wurde , die verschiedene Extras verspricht, einschließlich der frühzeitigen Unterstützung von Webanwendungen.
Bei der Arbeit entwickle ich mobile Anwendungen auf React Native, aber ich sehe Flutter neugierig an. Für diejenigen, die sich nicht auskennen: Auf Flutter können Sie jetzt Anwendungen für Android und iOS erstellen, die Unterstützung für Webanwendungen wird für die Veröffentlichung vorbereitet, und es gibt auch Pläne, Desktop zu unterstützen.
Dies ist "ein Ring, um alle zu regieren".
Nachdem ich mir ein paar Tage überlegt hatte, welche Art von Anwendung Sie versuchen können, entschied ich mich, eine Aufgabe mit einem Sternchen zu wählen - was brauchen wir für diese abgenutzten Tracks? Schwinge auf dem Desktop und überwinde heldenhaft Schwierigkeiten! Mit Blick auf die Zukunft werde ich sagen, dass fast keine Schwierigkeiten aufgetreten sind.
Under the Cut - eine Geschichte darüber, wie ich die üblichen Aufgaben des React Native-Programmierers mit Flutter-Werkzeugen gelöst habe, sowie den allgemeinen Eindruck der Technologie.

Als ich darüber nachdachte, welche Funktionen von Flutter ich „berühren“ möchte, entschied ich, dass in meiner Anwendung Folgendes sein sollte:
- Anforderungen an die Remote-API;
- Übergänge zwischen Bildschirmen;
- Übergangsanimationen
- Staatsmanager - Redux oder ähnliches.
Ich weiß nicht, wie man ein Backend erstellt, daher habe ich mich für eine offene API eines Drittanbieters entschieden. Aus diesem Grund habe ich mich für diese Ressource entschieden -
CBR-Kurse in XML und JSON, API . Nun, hier habe ich mich endlich für die Funktionalität der Anwendung entschieden: Es gibt zwei Bildschirme, auf dem Hauptbildschirm gibt es eine Liste der Währungen zum CBR-Kurs. Wenn Sie auf ein Listenelement klicken, wird ein Bildschirm mit detaillierten Informationen geöffnet.
Vorbereitung
Da der Befehl
flutter create
noch nicht weiß, wie ein Projekt für Windows / Linux erstellt wird (derzeit wird nur Mac unterstützt, verwenden Sie dazu das Flag
--macos
), müssen Sie
dieses Repository verwenden, in dem es ein vorbereitetes Beispiel gibt. Wir klonen das Repository, nehmen den
example
von dort, benennen ihn bei Bedarf um und arbeiten weiter daran.
Da sich die Unterstützung für Desktop-Plattformen noch in der Entwicklung befindet, müssen Sie noch eine Reihe von Manipulationen durchführen. Führen Sie im Terminal Folgendes aus, um auf die in der Entwicklung befindlichen Funktionen zuzugreifen:
flutter channel master flutter upgrade
Außerdem müssen Sie Flutter mitteilen, dass es Ihre Plattform verwenden kann:
flutter config --enable-linux-desktop
oder
flutter config --enable-macos-desktop
oder
flutter config --enable-windows-desktop
Wenn alles gut gegangen ist, sollten Sie durch Ausführen des Befehls
flutter doctor
eine ähnliche Ausgabe sehen:

Die Landschaft ist also fertig, das Publikum in der Halle - wir können beginnen.
Layout
Das erste, was nach React Native auffällt, ist das Fehlen einer speziellen Auszeichnungssprache a la JSX. Flutter zwingt Sie, sowohl Markup- als auch Geschäftslogik in
Dart zu schreiben. Das ist zunächst ärgerlich: Der Look hat nichts zu verstehen, der Code wirkt umständlich und selbst diese Klammern befinden sich am Ende der Komponente!
Zum Beispiel:

Und das ist nicht die Grenze! Es lohnt sich, einen an der falschen Stelle zu entfernen, und Ihnen ist ein angenehmer (kein) Zeitvertreib garantiert.
Aufgrund der Besonderheiten der Styling-Komponenten in Flutter nimmt bei großen Komponenten der Einzug vom linken Rand des Editors recht schnell zu und damit die Anzahl der zu schließenden Klammern.
Diese Funktion besteht darin, dass in Flutter-Stilen dieselben Komponenten verwendet werden (genauer gesagt Widgets).
Wenn ich in React Native drei Schaltflächen in einer Reihe in der
View
so
flexDirection: 'row'
, dass sie den Containerbereich gleichmäßig verteilen, reicht es aus,
flexDirection: 'row'
für die
View
in Stilen anzugeben und
flex: 1
für die Schaltflächen in den Stilen hinzuzufügen, dann hat Flutter eine separate Komponente
Row
zum Anordnen von Elementen in einer Zeile und eine separate Zeile zum "Erweitern" eines Elements über den gesamten verfügbaren Platz:
Expanded
.
Infolgedessen anstelle von
<View style={{height: 100, width:300, flexDirection: 'row'}}> <Button title='A' style={{flex:1}}> <Button title='B' style={{flex:1}}> <Button title='C' style={{flex:1}}> </View>
wir müssen so schreiben:
Container( height: 100, width: 300, child: Row( children: <Widget>[ Expanded( child: RaisedButton( onPressed: () {}, child: Text('A'), ), ), Expanded( child: RaisedButton( onPressed: () {}, child: Text('B'), ), ), Expanded( child: RaisedButton( onPressed: () {}, child: Text('C'), ), ), ], ), )
Ausführlicher, nicht wahr?
Oder Sie möchten diesem Container beispielsweise einen Rahmen mit abgerundeten Kanten hinzufügen. In React Native fügen wir einfach folgende Stile hinzu:
borderRadius: 5, borderWidth: 1, borderColor: '#ccc'
In Flutter müssen wir den Containerargumenten so etwas hinzufügen:
decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5)), border: Border.all(width: 1, color: Color(0xffcccccc)) ),
Im Allgemeinen verwandelte sich mein Markup zunächst in riesige Codeblätter, in denen sich der Teufel das Bein brechen würde. Allerdings ist nicht alles so schlecht.
Erstens müssen große Komponenten natürlich zerlegt werden - in separaten Widgets oder zumindest in den Methoden Ihrer Widget-Klasse.
Zweitens hilft das Flutter-Plugin in VS Code sehr - im obigen Bild sind Kommentare zu den Klammern vom Plugin selbst signiert (und sie können nicht gelöscht werden), was hilft, nicht in Klammern verwirrt zu werden. Plus Tools zur automatischen Formatierung - Nach einer halben Stunde müssen Sie regelmäßig
Ctrl+Shift+I
drücken, um den Code zu formatieren.
Außerdem wurde die Syntax der Dart-Sprache in der zweiten Ausgabe viel angenehmer, so dass ich sie am Ende des Tages bereits gerne benutzte. Ungewöhnlich? Ja Aber nicht unangenehm.
API-Anfragen
In React Native verwenden wir normalerweise die
fetch
, die
Promise
uns zurückgibt, um Daten von einer API
fetch
.
Bei Flutter ist die Situation ähnlich. Nachdem ich mir die Beispiele in der Dokumentation angesehen hatte, fügte ich das http-Paket zu
pubspec.yaml
(ein Analogon von
package.json
aus der JS-Welt) und schrieb so etwas:
Future<http.Response> getAnything() { return http.get(URL); }
Das
Future
Objekt hat eine sehr ähnliche Bedeutung wie Promise, daher ist hier alles ziemlich transparent. Nun, zum Serialisieren / Deserialisieren von JSON-Objekten können Sie das Konzept von Modellklassen mit speziellen Methoden von
fromJSON
/
toJSON
. Weitere Informationen hierzu finden Sie in der
Dokumentation .
Übergang zwischen Bildschirmen
Trotz der Tatsache, dass ich eine Desktop-Anwendung erstellt habe, gibt es aus Sicht von Flutter keinen Unterschied, auf welcher Plattform sie sich dreht. Nun, das heißt, in meinem Fall ist das im Allgemeinen so - ich weiß es nicht. Tatsächlich ist das Systemfenster, in dem die Flatteranwendung gestartet wird, der gleiche Bildschirm eines Smartphones.
Der Übergang zwischen Bildschirmen ist recht trivial: Wir erstellen eine Bildschirm-Widget-Klasse und verwenden dann die Standard-
Navigator
Klasse.
Im einfachsten Fall könnte es ungefähr so aussehen:
RaisedButton( child: Text('Go to Detail'), onPressed: () { Navigator.of(context).push<void>(MaterialPageRoute(builder: (context) => DetailScreen())); }, )
Wenn Ihre Anwendung über mehrere Bildschirme verfügt, ist es sinnvoller, zuerst ein
pushNamed
zu erstellen und dann die
pushNamed
Methode zu verwenden. Ein kleines Beispiel aus der Dokumentation:
class NavigationApp extends StatelessWidget {
Darüber hinaus können Sie eine spezielle Animation für den Wechsel zwischen Bildschirmen vorbereiten und Folgendes schreiben:
Navigator.of(context).push<void>(ScaleRoute(page: DetailScreen()));
Hier ist
ScaleRoute
eine spezielle Klasse zum Erstellen von Übergangsanimationen. Gute Beispiele für solche Animationen finden Sie
hier .
Staatsmanagement
Es kommt vor, dass wir von jedem Teil unserer Anwendung aus auf einige Daten zugreifen müssen. In React Native wird
redux
häufig (wenn nicht am häufigsten) für diese Zwecke verwendet.
Für Flutter gibt es ein
Repository , das Beispiele für die Verwendung verschiedener Anwendungsarchitekturen zeigt - es gibt Redux, MVC und MVU und sogar solche, von denen ich vorher noch nichts gehört habe.
Nachdem ich in diesen Beispielen ein wenig gestöbert hatte, beschloss ich, bei
Provider
anzuhalten.
Im Allgemeinen ist die Idee recht einfach: Wir erstellen eine spezielle Klasse,
ChangeNotifier
Klasse
ChangeNotifier
, in der wir unsere Daten speichern, sie mit den Methoden dieser Klasse aktualisieren und bei Bedarf von dort abrufen. Weitere Informationen finden Sie in der Paketdokumentation.
pubspec.yaml
Sie dazu das
provider
Paket zu
pubspec.yaml
und bereiten Sie die Provider-Klasse vor. In meinem Fall sieht es so aus:
import 'package:flutter/material.dart'; import 'package:rates_app/models/rate.dart'; class RateProvider extends ChangeNotifier { Rate currentrate; void setCurrentRate(Rate rate) { this.currentrate = rate; notifyListeners(); } }
Hier ist
Rate
meine Währungsmodellklasse (mit
currentrate
,
code
,
value
usw.),
currentrate
ist das Feld, in dem die ausgewählte Währung gespeichert wird, und
setCurrentRate
ist die Methode, mit der der
currentrate
Wert
currentrate
.
Um unseren Provider an die Anwendung anzuhängen, ändern wir den Anwendungsklassencode:
@override Widget build(BuildContext context) { return ChangeNotifierProvider( builder: (context) => RateProvider(),
Das war's, wenn wir die ausgewählte Währung speichern wollen, dann schreiben wir so etwas:
Provider.of<RateProvider>(context).setCurrentRate(rate);
Und wenn wir den gespeicherten Wert erhalten möchten, dann ist dies:
var rate = Provider.of<RateProvider>(context).currentrate;
Alles ist ziemlich transparent und keine Boilerplate (im Gegensatz zu Redux). Natürlich wird für komplexere Anwendungen vielleicht alles nicht so reibungslos verlaufen, aber für diejenigen wie mein Beispiel reine Weine.
Anwendung erstellen
Theoretisch wird der Befehl
flutter build <platform>
verwendet, um die Anwendung zu erstellen. In der Praxis erhielt ich beim
flutter build linux
Befehls
flutter build linux
die folgende Meldung:

"Es hat nicht wehgetan", dachte ich, ich war entsetzt über das Gewicht des
build
Ordners - 287,5 MB - und wegen der Einfachheit meiner Seele habe ich diesen Ordner für immer gelöscht. Wie sich herausstellte - vergebens.
Nach dem Löschen des
build
Verzeichnisses wurde das Projekt nicht mehr gestartet. Ich konnte es nicht wiederherstellen, also habe ich es aus dem ursprünglichen Beispiel kopiert. Es hat nicht geholfen - der Sammler schwor auf die fehlenden Dateien.
Nach einigen Recherchen stellte sich heraus, dass sich in diesem Ordner eine Datei
snapshot_blob.bin.d
, die anscheinend Pfade zu allen im Projekt verwendeten Dateien enthält. Ich habe die fehlenden Pfade hinzugefügt und es hat funktioniert.
Daher weiß Flutter derzeit nicht, wie Release-Builds für den Desktop vorbereitet werden sollen. Jedenfalls für Linux.
Wenn Sie Ihre Augen vor diesem Minus schließen, hat sich die Anwendung im Allgemeinen so entwickelt, wie ich es wollte und wie sie aussieht
Bonus
Wir gehen zum versprochenen Bonus über.
Schon beim Schreiben der Anwendung wollte ich prüfen, wie schwierig es sein würde, sie auf andere Plattformen zu portieren. Beginnen wir mit dem Handy.
Sicher gibt es einen weniger barbarischen Weg, aber ich entschied, dass der kürzeste Weg direkt ist. Aus diesem
pubspec.yaml
ich einfach ein neues Flutter-Projekt erstellt, die Datei
pubspec.yaml
, die
assets
,
fonts
und
lib
Verzeichnisse übertragen und die Zeile zu
AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
Die Anwendung begann mit einem halben Tritt und ich bekam dies
Zuerst musste ich am Web basteln. Ich wusste nicht, wie man ein Webprojekt erstellt, deshalb habe ich die Anweisungen aus dem Internet verwendet, die aus irgendeinem Grund nicht funktionierten. Ich wollte schon spucken, bin aber auf
dieses Handbuch gestoßen.
Infolgedessen stellte sich heraus, dass alles so einfach wie möglich war - es musste lediglich die Unterstützung für Webanwendungen einbezogen werden. Drücken Sie aus dem Handbuch:
flutter channel master flutter upgrade flutter config --enable-web cd <into project directory> flutter create . flutter run -d chrome
Dann habe ich die notwendigen Dateien auf die gleiche barbarische Weise in dieses Projekt übertragen und solche erhalten
Allgemeine Eindrücke
Anfangs war die Arbeit mit Flutter ungewöhnlich, ich habe ständig versucht, die üblichen Ansätze von React Native zu verwenden, und dies störte. Auch eine gewisse Redundanz des Dartcodes war etwas ärgerlich.
Nachdem ich meine Hand (und Zapfen) ein wenig bekommen hatte, begann ich die Vorteile von Flutter gegenüber React Native zu erkennen. Ich werde einige auflisten.
Sprache . Dart ist eine völlig verständliche und nette Sprache mit starker statischer Typisierung. Nach JavaScript war es wie ein Hauch frischer Luft. Ich hatte keine Angst mehr, dass mein Code zur Laufzeit kaputt gehen könnte, und es war ein angenehmes Gefühl. Jemand mag sagen, dass es Flow und TypeScript gibt, aber das ist es nicht - in unseren Projekten haben wir beide verwendet, und irgendwo ist immer etwas anderes kaputt gegangen. Wenn ich in React Native schreibe, kann ich nicht anders, als das Gefühl zu haben, dass sich mein Code auf Streichholzstützen befindet, die jederzeit kaputt gehen können. Bei Flutter habe ich dieses Gefühl vergessen, und wenn der Preis Code-Redundanz ist, bin ich bereit, ihn zu bezahlen.
Plattform . In React Native verwenden Sie native Komponenten. Dies ist im Allgemeinen gut. Aus diesem Grund müssen Sie manchmal plattformspezifischen Code schreiben und plattformspezifische Fehler abfangen. Es kann unglaublich anstrengend sein. Mit Flutter können Sie diese Probleme wie einen Albtraum vergessen (obwohl es bei großen Anwendungen möglicherweise nicht so reibungslos läuft).
Die Umwelt . Mit der Umgebung in React Native ist alles traurig. Die vscode-Plugins fallen ständig ab, der Debugger kann 16 Gig Operative und 70 Gig Swap verschlingen, das System (aus persönlicher Erfahrung) fest aufhängen und das häufigste Fehlerkorrektur-Szenario: "Entfernen Sie node_modules, installieren Sie Pakete erneut und versuchen Sie mehrmals, neu zu starten." Das hilft normalerweise, aber bljad! Nicht so sollte es sein, nicht so.
Darüber hinaus müssen Sie AndroidStudio und Xcode regelmäßig ausführen, da einige nur auf diese Weise erstellt werden (fairerweise wurde dies mit der Veröffentlichung von RN 0.60 besser).
Vor diesem Hintergrund sieht das offizielle Flutter-Plugin für vscode sehr gut aus. Hinweise zum Code ermöglichen es Ihnen, sich mit der Plattform vertraut zu machen, ohne die Dokumentation zu lesen. Die automatische Formatierung löst das Problem mit dem Codierungsstil, dem normalen Debugger usw.
Im Allgemeinen sieht es nach einem ausgereifteren Werkzeug aus.
Plattformübergreifend . React Native bekennt sich zum Prinzip „Einmal lernen, überall schreiben“ - sobald Sie gelernt haben, können Sie für verschiedene Plattformen schreiben. Richtig, unter jeder Plattform treten spezifische Probleme auf. Aber vielleicht ist dies nur eine Folge der Unreife von React Native - im Moment ist die neueste stabile Version 0.61. Möglicherweise werden mit der Veröffentlichung von Version 1.0 die meisten dieser Probleme behoben.
Der Flutter-Ansatz ist eher wie einmal schreiben, überall kompilieren. Und selbst wenn der Desktop momentan nicht produktionsbereit ist, ist das Web auch in Alpha, aber alles geht dahin. Die Möglichkeit, eine einzige Codebasis für alle Plattformen zu haben, ist ein starkes Argument.
Natürlich ist Flutter auch nicht ohne Mängel, aber ein wenig Erfahrung in der Verwendung erlaubt es mir nicht, sie zu identifizieren. Wenn Sie also eine objektivere Bewertung wünschen, können Sie den Neuheitseffekt ignorieren.
Im Allgemeinen sollte beachtet werden, dass Flutter überwiegend positive Gefühle hinterlassen hat, obwohl er Raum zum Wachsen hat. Und beim nächsten Projekt wäre ich eher bereit, damit zu beginnen, und nicht mit React Native.
Der Quellcode für das Projekt ist auf
GitHub zu finden.
PS Ich nutze diese Gelegenheit, um allen Beteiligten am vergangenen Lehrertag zu gratulieren.