Mobile Apps schneller entwickeln mit Googles mobilem Framework: Flotter mit Flutter
„Build a better way to develop for mobile“ – so das Motto, als Google vor mehr als zwei Jahren die Arbeit an einem neuen Framework für die Android- und iOS-App-Entwicklung begann. Das Team analysierte zunächst alle bestehenden Ansätze zur
Cross-Plattform-Entwicklung: Hybride Apps, Toolkits für Cross-Plattform-Apps, Programmiersprachen und Frameworks. Eine Umfrage
unter App-Entwicklern brachte eine Reihe von Problemen ans Licht. So ist die Entwicklung von Android- und iOS-Apps aus ihrer Sicht unnötig langsam und teuer, weil je ein Team, eine Programmiersprache, ein Framework und verschiedene APIs für unterschiedliche Devices notwendig sind. Dazu kommt, dass beide Systeme Funktionen unterschiedlich ausführen.
Außerdem kann das Deployment von Apps nach Code-Änderungen bei Google von
einer bis zu über zwanzig Minuten dauern, ein Clean Build einer komplexen App sogar bis zu einer Stunde. Dementsprechend schwierig ist es, eine wirklich herausragende User-Experience für iOS und Android abzuliefern – vor allem bei hybriden Apps. Dagegen haben die App-Anwender sogar einen höheren Anspruch an die Qualität von Apps als an Desktop- oder Web-Anwendungen.
Kein Wunder, dass die Ziele von Flutter – damals noch unter dem Projektnamen „Sky“ bekannt – hoch gesteckt waren: Es sollte keine Kompromisse bei der Performance und beim Design geben und iOS- sowie Android-Apps sollten sich mit einer gemeinsamen Code-Basis entwickeln lassen.
Im Idealfall liefern die einmal realisierten Funktionen auf beiden Plattformen die gleiche User-Experience. App-Entwickler sollten Custom-Components mit einem eigenen Look einfach erstellen und mit gleicher Optik auf beiden Plattformen ausliefern können. Die Frame-Rate von 60 fps sorgt dafür, dass Flutter-Apps auch auf älteren Smartphones und OS-Versionen performant laufen. Und schließlich sollte die Funktion „Hot Reload“ Code-Änderungen in weniger als einer Sekunde auf das Device übertragen.
Der flexible Stack des Flutter-Frameworks
Das Flutter-Team begann damit, verschiedene Programmiersprachen und Entwicklungsansätze zu testen. Es realisierte ein komplettes hybrides Framework und verwarf es wieder. Dann wurde es im Technologie-Stack von Chrome und Android fündig: jahrelang im Produktionseinsatz erprobte Software-Komponenten, die unter vielen Software-Layern verborgen lagen.
Die Anordnung dieser Komponenten in größere Software-Produkte – wie etwa in den Webkit-Browser – war für Desktop-Systeme sinnvoll. Doch für die mobile Entwicklung war ein Großteil der Funktionen nicht notwendig. Deshalb optimierte das Team diese für Flutter, bevor es sie in das Framework integrierte. Dazu gehören unter anderem der Grafik-Stack von Chrome und Android, die Text-Rendering-Engine von Webkit und Chrome sowie die Programmiersprache Dart mit der Dart-VM.
Weil die Rückmeldungen der befragten Entwickler nahelegten, dass monolithische Frameworks (die nur die obersten API-Ebenen freilegen) nicht erwünscht sind, ist Flutter so angelegt, dass Entwickler entscheiden können, auf welche Teile von Flutter ihre Entwicklung aufbauen soll: Auf die Material-Design-UI-Komponenten (sie sind Teil des Frameworks), die Base-Classes für Widgets, die Rendering-Layer-APIs, die Composition-Layer-APIs oder die Gesture-APIs.

Spannend für Entwickler: Sie können selbst entscheiden, auf welche Teile des Frameworks sie ihre App aufbauen wollen –etwa auf Widget-Ebene oder auf dem Rendering-Layer. (Grafik: Flutter)
Dies ist zum Beispiel notwendig, wenn sich Widgets OS-spezifisch verhalten sollen. Die Flexibilität hat ihren Preis: mehr Komplexität. Wer die Rendering-API nutzen will, muss auch die entsprechenden Regeln und Zusammenhänge verstehen. Alle Klassen sind aber so dokumentiert, dass eine Einarbeitung gut möglich ist.
In Sachen Design ergaben die App- und Play-Store-Analysen des Flutter-Teams, dass vor allem Apps mit eigenem Style und einem hohen Anteil an Custom-UI-Widgets populär sind. Da Flutter nicht die UI-Widgets des Betriebssystems verwendet, haben Designer freie Hand bei der Gestaltung ihrer Interfaces. Flutter stellt Custom-UI-Widgets unabhängig von der Plattform immer in der gleichen Qualität dar – gleiches gilt auch für die Textdarstellung.
Außerdem sind die Funktionen einer Flutter-App nicht von der Betriebssystemversion abhängig (sie unterstützen die Android-Versionen 4.1.x bis 7.x und iOS ab Version 8/iPhone 5s oder neuer). Zu einer guten User-Experience trägt auch bei, dass Animationen flüssig mit 60 fps laufen.
Hauptkomponenten von Flutter |
|
Warum ausgerechnet Dart? Performance!
Da ein Großteil von Flutter in Dart geschrieben ist, können Entwickler den gesamten Framework-Quellcode
aus der IDE heraus lesen und debuggen. Zudem enthält jede Flutter-App eine Dart-VM-Instanz, die
komplett in Dart verfasst ist. Für OS-spezifische Funktionen,
für die es noch keine Dart-API gibt, können Entwickler Flutter-Services anlegen, welche die bidirektionale Kommunikation zwischen der
Dart-VM und Java oder ObjectiveC ermöglichen.
Ein Grund für die Wahl von Dart ist erhöhte Geschwindigkeit bei der Entwicklung: Durch die gemeinsame Code-Basis für Android- und iOS-Apps soll sich die Entwicklungsgeschwindigkeit bis um das Dreifache steigern lassen, berichtet das Google-Team. Darüber hinaus bietet Dart die objektorientierte Entwicklung von visuellen User-Experiences – und diese hat sich über die letzten 30 Jahre als überaus erfolgreicher Ansatz bewährt. Die gute OOP-Unterstützung von Dart ist dabei ebenfalls ein Plus für Flutter.
Die für Mobilgeräte optimierte Dart VM gewährleistet zudem eine beständige, gute Performance – auch auf älteren Mobilgeräten. Dart kann auch kleine Memory-Segmente in sehr kurzer Zeit zuweisen und so eine gute Performance des Functional-Reactive-Programmiermodells von Flutter sicherstellen.
Ein weiterer Vorteil ist, dass Google die Sprache und die Dart-VM selbst entwickelt. Das Dart-VM-Team kann somit die vom Flutter-Team gewünschten Funktionen zeitnah in den Dart-Technologie-Stack einbauen. Beispiele solcher speziell für Flutter entwickelten Features sind eine neue Dart-VM mit Unterstützung von AOT Compilation sowie der Strong Mode, der ein restriktives Type-System für Dart darstellt.
Und auch der Tooling-Support in IntelliJ und bei Verwendung des Flutter-Kommandozeilen-Tools ist exzellent. Wer IntelliJ scheut, findet in Atom oder Visual Studio Code alternative Editoren mit Dart-Unterstützung.
Einfacher Einstieg: Demo-App mit Counter
Nach all der Theorie ist es Zeit für ein bisschen Praxis: Eine Flutter-App, die auf einem Device startet und Flutters Hot Reload testet. Derzeit unterstützt das Framework nur Linux und macOS, Windows soll folgen. Eine ausführliche Beschreibung der nachfolgenden Schritte liefert auch das „Getting Started Tutorial“.
Nachdem Dart und Flutter installiert sind, folgt das Setup für Android- und iOS-Apps (unter OS X). Der Befehl „flutter create“ legt eine entsprechende Flutter-App an.
Flutter-Projekt anlegen
$ flutter create helloworld
Listing 1
Die Anweisung „flutter run“ startet die Demo-App (die Anwendung in diesem Beispiel ist für Android gemacht, für iOS sähe die Ausgabe etwas anders aus). Die folgende Anweisung installiert die App auf dem mobilen Endgerät und stellt eine Verbindung zum Debugger her.
Die Beispiel-App verwendet dabei für den Counter-Button die Material-Design-Widgets. Es ließen sich natürlich auch eigene Designs entwickeln.
App installieren und starten
$ flutter run Running 'flutter packages get' in helloworld... 482ms Launching lib/main.dart on SM N920S in debug mode... Building APK in debug mode (android-arm)... 5151ms Installing build/app.apk... 8230ms Diagnostic server listening on http://127.0.0.1:8101 Observatory listening on http://127.0.0.1:8100/ Syncing files to device... 1917ms To hot reload your app on the fly, press "r" or F5. To restart the app entirely, press "R". The Observatory debugger and profiler is available at: http://127.0.0.1:8100/ For a more detailed help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.
Listing 2
Schnell, schneller, Hot Reloading: Das kann die Funktion
Eine der beeindruckendsten neuen Funktionen des Frameworks ist das Hot Reloading. Um dieses Feature zu testen, soll sich der Text „Button tapped“ in „Floating Button pressed“ ändern. Der String befindet sich in Zeile 80 der Datei „lib/main.dart“.
Textänderung injizieren
body: new Center( child: new Text( 'Button tapped $_counter time${ _counter == 1 ? '' : 's' }.', ), ),
Listing 3
Der folgende Code ändert die Zeile und speichert die Datei.
Code-Zeile ändern und speichern
'Floating Button pressed $_counter time${ _counter == 1 ? '' : 's' }.',
Listing 4
Der Prozess „flutter run“ kann nach dem Start der App weitere Befehle von der Kommandozeile entgegennehmen. Die Ausgabe beim Start der Flutter App zeigt folgenden Satz an:
App neu laden
To hot reload your app on the fly, press "r" or F5. To restart the app entirely, press "R".
Listing 5
Bei Betätigen der R-Taste oder „F5“ übernimmt das Programm die Änderungen. Dabei bleibt der Zustand (State) der App erhalten, der Counter ändert seinen Wert also nicht.
Bestätigung für den Hot Reload
Performing hot reload... 712ms Reloaded 1 of 382 libraries.
Listing 6
Das Hot Reload dauert in diesem Fall unter einer Sekunde. Gibt man auf der Kommandozeile „R“ (groß geschrieben) ein, startet die Dart-VM in der App neu – der State geht verloren. Für einen Neustart der Dart-VM braucht Flutter ein bis zwei Sekunden.
Fazit
Aktuell hat Flutter noch den Status eines Early-Stage-Open-Source-Projekts. Es unterstützt noch nicht alle Arten von Apps und auch die Zahl der Widgets ist noch begrenzt. Doch bei Google entwickeln bereits mehrere Teams Apps mit Flutter und die Dokumentation ist gut genug, um problemlos einzusteigen.
Selbst in der Preview-Version löst Flutter schon viele Probleme – das enorme Potenzial lässt sich also bereits erkennen. Die Performance sieht vielversprechend aus, der Entwickler-Workflow ist schlank. Und dass Google für das UI des neuen Fuchsia-OS auf Flutter setzt, lässt auf dessen große Zukunft hoffen.