c't 11/2018
S. 90
Hintergrund
Android- und iOS-Entwicklung

Flatterige Pfeile

Android- und iOS-Entwicklung mit Dart und Google Flutter

Googles anfangs nur intern genutztes Framework Flutter ermöglicht es, Android- und iOS-Apps aus einem Code zu entwickeln. Änderungen landen dabei sekundenschnell auf Testgeräten und Emulator. Doch um sich zwischen ReactNative, PhoneGap, Xamarin und Qt zu etablieren, muss Flutter mehr bieten.

Bei einem guten Kompromiss sind alle unzufrieden – scheinbar hat Google die Programmiersprache von Flutter nach diesem Prinzip ausgewählt. Weder kommen die Android-Sprachen Java oder Kotlin zum Einsatz, noch die iOS-Sprachen Swift und Objective C, selbst auf den gemeinsamen Nenner C++ ist die Wahl nicht gefallen. Auch das bei Kontrahenten wie ReactNative oder PhoneGap genutzte JavaScript wurde es nicht. Stattdessen kommt Dart zum Einsatz, eine von Google entworfene Sprache, die mit einigen Nachteilen von JavaScript aufräumen soll.

Immerhin ist Dart eine moderne Sprache, die dem Programmierer viel Arbeit abnimmt – auch wenn sie teils etwas geschwätziger als Kotlin wirkt. Entwickler dürften weder mit Dart noch mit der Struktur von Flutter ernsthafte Probleme bekommen. Als Entwicklungsumgebung unterstützt Flutter Android Studio, IntelliJ und Visual Studio, lässt sich aber auch mit anderen Editoren verbinden. Zum Erzeugen von iOS-Apps benötigt man einen Mac.

Für Dart existieren sowohl Compiler als auch schnelle VMs, was Flutter für eine zweigeteilte Architektur nutzt: Zum einen werden fertige Apps im Interesse einer besseren Performance auf dem Entwicklungsrechner in Maschinencode kompiliert und mit einer kleinen Runtime versehen. Zum anderen läuft während der Entwicklung auf den Testgeräten eine Debug-Runtime mit Dart-VM. Die bekommt bei Code-Änderungen keine komplett kompilierte App geschickt, sondern nur den geänderten Code. Die VM jagt ihn dann durch einen JIT-Compiler und führt die App ohne Unterbrechung fort.

Ohne Sekundenschlaf

Dabei bleiben die Inhalte privater Member der geänderten Klassen erhalten, sodass man tatsächlich den Code einer laufenden App austauschen kann, ohne dass beispielsweise in Formularen schon getätigte Eingaben verloren gehen. Die Übertragung geht blitzschnell, der neue Code läuft, bevor man nach dem Speichern in der IDE auch nur den Blick aufs Testgerät oder Emulator gerichtet hat.

Bei größeren Änderungen, etwa Umbauten an der Klassenstruktur oder den Members einer Klasse, stößt das an seine Grenzen, ebenso bei geänderten final-Deklarationen. Manche dieser Fälle erkennt die IDE und schlägt einen kompletten Restart vor. Selbst der geht inklusive der Vorarbeiten in der IDE viel schneller vonstatten als mit Java/Kotlin üblich. Lediglich der erste Start einer App dauert üblich lang. Die Beta startete allerdings oft eine veraltete App-Version, sodass man flutter clear im Terminalfenster eingeben oder das Build-Verzeichnis löschen muss; ein hoffentlich bald behobener Fehler.

Ohne GUI-Builder

Diese schnellen Turnaround-Zeiten sind in einer Hinsicht aber auch nötig: Flutter kommt ohne grafischen GUI-Editor und ohne Beschreibungssprache, sondern der Entwickler entwirft die Bedienschnittstelle ausschließlich in normalem Flutter-Code. Dabei baut man sowohl Bedienelemente als auch Layout-Vorgaben in einer Widget-Struktur auf, die man in komfortablen Konstruktor-Kaskaden erzeugt:

Widget build(BuildContext context) {

return new MaterialApp(

title: 'Flutter-Test',

home: new Scaffold(

appBar: new AppBar(

title: new Text('Flutter Test')),

body: new Center(

child: new Text('Hello

${Platform.operatingSystem}'))

));}

In einem Constructor kann man auch Listener unterbringen und somit beispielsweise Knöpfe direkt mit Funktionen ausstatten. Als Tipphilfe gibt es den „fat arrow“, der einzeilige Funktionen der Form {return x;} zu => x; abkürzt, zudem dürfen in Dart 2.0 die Schlüsselwörter new und const entfallen.

Zudem ist es möglich, von weiteren Bedingungen abhängig zu machen, welche Widgets die App erzeugt. Beispielsweise könnte man die App auf Android und iOS unterschiedliche Widgets nutzen lassen, indem man die in dart:io befindliche Platform.isAndroid() oder .isIOS() abfragt. Oder man baut mit MediaQuery.of(context).orientation im Hoch- und Querformat unterschiedliche Widgets.

Ohne Änderungen

Die grafischen Widgets zeichnen sich ohne Rückgriff auf die nativen Elemente des Betriebssystems selbst über eine Flutter-eigene Rendering-Engine. Daher funktioniert das von Android nachgebaute Material-Design unter iOS, und die von iOS nachgebauten Steuerelemente unter Android. Sie sind Wegwerfelemente mit unveränderlichem Inhalt, die das Framework häufig verwirft und neu erzeugt, statt sie aufwendig zu cachen. Für 3D-Anwendungen eignet sich Flutter nicht.

Die meisten der Flutter-Widgets orientieren sich an Googles eher unter Android verbreitetem Material Design. Doch auch ein paar im „Cupertino“-Style gibt es – und Layouts sind ebenfalls Widgets.

Die veränderlichen Daten etwa eines Eingabefelds stecken in einem Paar aus State-Objekt und StatefulWidget, die beide keine direkte grafische Repräsentation haben. State reagiert auf Nutzereingaben und erzeugt nach jeder Datenänderung eine neue Widget-Kaskade mit den aktuellen Inhalten.

Ein State kann durchaus für eine ganze Reihe von Eingabefeldern oder auch alle eines Formulars verantwortlich sein, was die Verdrahtung vereinfacht. Dennoch ist ein Effizienzverlust gegenüber den wenigen bei Android und iOS nötigen Zeilen zumindest anfänglich spürbar.

Ohne Dart

Über ein package-System lassen sich fertige Module einbinden oder selbst einfach neue Module erzeugen. Einiges gibt es schon, doch mit dem vielfältigen Angebot an Modulen, Plug-ins und ähnlichem, das es für andere Crossplattform-Systeme gibt, hält Flutter noch nicht mit.

Android und iOS-Apps aus einem Source, das schafft Flutter gut. Die Apps nutzen aber nicht die nativen Grafikelemente der Plattformen.

Das Einbinden von nativem Code in Java, Kotlin, Objective C und Swing ist mit Platform Channels möglich, die ein einfaches Messaging-System von und zu Dart implementieren. Dazu muss man die iOS- und Android-Stubs erweitern, die zu jedem Flutter-Projekt gehören, und dort seinen Code unterbringen. Solche Lösungen lassen sich auch als Package verpacken und weitergeben.

Das Einbinden nativer grafischer Elemente ist hierüber allerdings nicht vorgesehen. Auch von eigenem Code in C/C++ ist nirgends die Rede, obwohl der Flutter-Kern in C++ implementiert ist. Das über die Platform Channels zu realisieren, mag möglich sein, wenn man sich intensiv mit Gradle und dem NDK auseinandersetzt, die Zweifach-Kapselung dürfte aber Performance kosten. Anders herum lassen sich Flutter-Views in bestehende Android- und iOS-Apps einbinden.

Ohne Unabhängigkeit

Mit Blick auf iOS und Android ist Flutter ein Crossplattform-Framework unter vielen: einerseits blitzschnell beim Testen, kostenlos, effizient durch die Beschreibung von Code und Oberfläche in einer gemeinsamen Sprache, andererseits noch spürbar im Betastadium, auf das nicht so beliebte Dart festgelegt, zumindest bisher ohne C/C++ und vermutlich auch zukünftig ohne native Widgets.

Weitere Plattformen unterstützt Flutter nicht, Google schließt Web-Apps sogar explizit aus. Auf der nach Redaktionsschluss stattfindenden Hausmesse Google I/O dürfte Neues über Chrome OS oder Fuchsia zu erfahren sein, vielleicht auch zu Windows-, macOS- oder Linux-Ablegern.

Genau von dieser Offenheit hängt es ab, wie zukunftsträchtig Flutter sein wird. Schließlich geht man eine enge Bindung mit Google ein – obwohl man sich durch ein Crossplattform-Tool doch gerade vom Betriebssystem-Hersteller unabhängig machen wollte.

Flutter stammt nicht aus Googles Android-Abteilung, sondern aus der Werbeabteilung, die ihre Dienste betriebssystemunabhängig vermarkten möchte. Doch wenn Flutter andererseits zu sehr im Googleversum aus Android, Fuchsia und vielleicht Chrome OS stecken bleibt und darüber hinaus gerade mal iOS abdeckt: Dann stehen die Chancen nicht gut, dass Flutter zukünftig auch Betriebssysteme abdeckt, die nicht von Google stammen. Und dann dürfte es auch nicht helfen, dass sowohl Flutter als auch Dart Open Source sind. (jow@ct.de)