Op 4 december 2018 heeft Google de eerste stabiele release aangekondigd van het open source framework Flutter voor de programmeertaal Dart. Met Flutter is het op dit moment mogelijk om apps te bouwen voor zowel Android als iOS. In dit artikel leg ik uit hoe Flutter werkt en wat precies de plannen van Google met Flutter zijn.
Auteur: Rogier van Apeldoorn
De eerste versie van Flutter, genaamd “Sky”, werkte alleen op Android en werd in 2015 op de Dart Developer summit gepresenteerd. Google is begonnen met het strippen van de Chrome Browser. Wat overbleef, was een render engine die ruim twintig keer zo snel was als de Chrome Browser. Met deze render engine wordt dus de app op het scherm gerendert. Vervolgens is geëxperimenteerd met Javascript. Al snel bleek dat dit niet werkte en is gekozen voor de programmeertaal Dart. Dart is nu de taal waarmee een Flutter app kan worden gebouwd.
Dart is misschien wel de enige mainstream taal die zowel just-in-time als a-head-of-time compilatie ondersteunt. Door beide vormen van compilatie te ondersteunen, heb je de voordelen van beide werelden. Met just-in-time compilatie zorgt Dart ervoor dat het ontwikkelen van een Flutter project heel snel kan verlopen. Dit komt doordat de wijzigingen die je maakt tijdens het ontwikkelen, direct zichtbaar zijn in je app. Als we een app uitbrengen, dan zal een release met a-head-of-time compilatie worden uitgebracht. Dit zorgt voor snelle opstarttijden en hoge performance van de app. De Flutter engine is hoofdzakelijk geschreven in C++. Dat maakt weer gebruik van Google’s Skia library dat voor de rendering zorgt op de verschillende platformen.
De installatie van Flutter is relatief simpel. Je gaat naar de website https://flutter.dev en volgt de installatiehandleiding. Flutter kan op Windows, macOS en Linux worden geïnstalleerd. De Flutter en Dart plugins zijn beschikbaar voor de gangbare IDE’s, zoals Android Studio, IntelliJ en Visual Studio Code. Het installeren en het beginnen met Flutter is gemakkelijk. Het leren van Dart is ook niet heel moeilijk. Als ontwikkelaar kan je daarom al snel uit de voeten met Dart.
Een app in Flutter bestaat uit widgets. Door widgets samen te stellen, kan je weer nieuwe widgets creëren, hierdoor ontstaat een widget tree. Het renderen van een app op het scherm gaat met maximaal 120 fps. Dat betekent dat de app supersmooth aanvoelt. Maar hoe doen ze dat? Het renderen van de app op het scherm gebeurt in Flutter met drie verschillende trees. Eén voor de widgets, één voor de elementen en één voor de render objecten.
De render tree zorgt voor de lay-out en tekent de app op het scherm. Dit zijn dure operaties die veel tijd kosten. Het is daarom handig om dit zo min mogelijk te doen en zoveel mogelijk hetgeen op het scherm staat te recyclen en te cachen. Het recyclen en cachen van render objecten gebeurt in de Element tree. Dit is de ‘lijm’ tussen de immutable widgets en de mutable render objecten. De element tree is eigenlijk heel goed in het vergelijken van widget objecten en render objecten en past de bestaande render objecten zoveel mogelijk aan.
Een app in Flutter bouw je met widgets. In Flutter zijn twee type widgets, stateless widgets en stateful widgets. Een stateless widget is een immutable configuratie, een blauwdruk voor een element. Een stateless widget hoeft geen state bij te houden en heeft alleen te maken met de data die initieel in de widget tijdens constructie is meegegeven. Deze data zal ook niet meer wijzigen. Denk hierbij aan een tekst label of een icoon. Eigenlijk bepaalt de parent widget de state van de stateless widget. Stateful widgets zijn dynamisch en bevatten wel een state.
Stateful widgets stellen ons in staat om de content te wijzigen. Dit kan gebeuren doordat de gebruiker ergens op drukt, als response op een asynchrone call of als er een state wijziging is in de app. Een Stateful widget extend de StatefulWidget class. Net als Stateless kan een Stateful widget ook constructieparameters verwachten waarmee de initiële state wordt gezet. De StatefulWidget class bevat een functie createState welke we moeten overriden. In de functie createState moeten we een nieuwe state van de widget teruggeven. De state die we teruggeven, moet een extensie zijn van de State class. Deze State class bevat een build functie die de uiteindelijke widget teruggeeft. Door het wijzigen van de state in de setState functie informeren we Flutter dat een state change heeft plaatsgevonden. Flutter zal de build functie uitvoeren om zo een nieuwe widget te creëren. Om de theorie wat duidelijker te maken, staan hieronder twee voorbeelden van een stateless widget en een stateful widget.
De eerste widget die ik gebruik, is de RawMaterialButton. Naast een aantal parameters, zoals kleur en shape, heeft bijna iedere widget de mogelijkheid tot het toevoegen van een andere widget in de vorm van een child. In dit geval voeg ik de Row widget toe, omdat ik graag een icoon en een tekst aan mijn button wil toevoegen. De Row widget neemt standaard de volledig beschikbare ruimte in. Als ik verder niets configureer aan de Row widget, dan zou dit betekenen dat er een button over de volledige breedte van het scherm zou ontstaan. Dit kan voorkomen worden door MainAxisSize van de Row widget in te stellen. Het mooie aan een Row Widget is natuurlijk dat hierin meerdere children kunnen, zodat ik zowel een Icon widget als een Text widget kan toevoegen. Na het toevoegen van Icon widget en de Text widget staan de widgets tegen elkaar aan. Door tussen beide widgets een SizedBox widget te zetten, zorgt deze ervoor dat er 10 pixels ruimte is tussen het icoon en de tekst.
Met dit voorbeeld is duidelijk geworden hoe je een stateless widget kan maken en hoe je van meerdere widgets weer een nieuwe widget kan maken.
We willen ook de waarde van bijvoorbeeld een tekst binnen een app kunnen updaten of widgets kunnen vervangen door ander widgets. Dit doen we met behulp van stateful widgets. In onderstaand voorbeeld extend MyHomePage class van StatefulWidget. De class StatefulWidget bevat de createState methode die we moeten overriden. De functie createState geeft altijd een nieuwe state terug. In dit geval geven we de _MyHomePageState terug. De _MyHomePageState is weer een extensie van class State en bevat de build functie. De build functie geeft de widget terug. In het geval dat de state van de widget in de setState functie wordt aangepast, zal Flutter opnieuw de build functie aanroepen om zo een nieuwe widget te krijgen met daarin de aangepaste waarde.
Gelukkig is het niet nodig om alle widgets zelf te bouwen in Flutter. Sterker nog, doordat Flutter volledig gebruik maakt van de principes van Material Design is het heel eenvoudig een mooie en goedwerkende app te bouwen. Wil je echter een specifiek knopje, switch of tabel lay-out van iOS, dan zijn er de Cupertino widgets die alle elements pixel perfect van iOS bevatten. Veel widgets kunnen gevonden worden in de Material Design widgets en vormen vaak de basis van een app. De Material Design afdeling van Google gebruikt Flutter als speeltuin voor hun laatste ideeën. Hierdoor zijn de Material Design widgets erg uitgebreid. Met Material Design kan je een app bouwen die prettig aanvoelt voor beide platformen. Het betekent niet dat een app eruit gaat zien als een Google app. Het mooie aan Material Design is dat je volledige controle hebt over hoe je app eruit komt te zien.
Er zijn veel verschillende type widgets. Zo is er bijvoorbeeld een GestureDetector widget.
Wrappen we een widget met de GestureDetector, dan kan Tap, LongPress, Drag, enz. worden gedetecteerd.
Eén van mijn favoriete Widgets is de Hero widget. Met de Hero widget geef je de gebruiker inzicht waar hij vandaan komt en waar hij naartoe navigeert. Stel, je hebt een lijst met een foto. Door de foto in een Hero widget met een ID te zetten en op de detailpagina dezelfde foto te plaatsen in een Hero widget met hetzelfde ID, zal Flutter het plaatje naar de nieuwe plaats animeren. Als je terug navigeert naar de lijst zal het plaatje van de detailpagina weer terug animeren in de lijst. Super cool!
Dit is één van de vele functionaliteiten die standaard in Flutter zit. Door gebruik te maken van de standaard widgets, kan al een mooie app gebouwd worden.
Met Flutter kan je echt heel snel ontwikkelen. Flutter is in staat code wijzigingen “on the fly” door te voeren in de app zonder de app opnieuw te bouwen of op te starten en zonder dat de app zijn state verliest. Tijdens het coderen van de app zie je het effect van de wijzigingen direct. Sla je je wijzigingen op, dan worden je wijzigingen direct naar de simulator gepushed. Dus je ziet je app letterlijk ontstaan op de simulator tijdens het coderen van je app. Code aanpassingen, zoals het wijzigen van de logica van de app, zijn ook direct zichtbaar. Het allermooiste is wel dat de state van de app behouden blijft. Na het opslaan van een wijziging zal je niet een loginproces door moeten of een winkelmandje moeten vullen om zo de testcase te creëren, waarin de bug zich voordeed om te zien of deze met de code wijziging is opgelost. De state van de app blijft behouden.
Het debuggen van een app is altijd een belangrijk onderdeel van het ontwikkelproces. Flutter biedt hier ook goede ondersteuning voor, in de vorm van een prima debugger en de Flutter inspector. Met de Flutter inspector kan je de volledige opbouw van je app analyseren.
Voor het verkrijgen van toegang tot bijvoorbeeld de camera, kan je gebruik maken van packages. Packages vind je op https://pub.dev/flutter en kunnen eenvoudig worden toegevoegd aan een app door de dependency toe te voegen aan de pubspec.yaml file. Veel packages zijn gemaakt door het Flutter team. Deze packages zijn van hoge kwaliteit en bevatten goede documentatie. Mocht het zijn dat je een functionaliteit niet kan vinden in één van de packages, dan kan je zelf packages schrijven. Houd er wel rekening mee dat zodra je een package schrijft en je wilt deze voor beide platformen publiceren, je een package moet schrijven die beide platformen moet ondersteunen.
Tijdens de Google IO 2019 is het preview project “Flutter for the Web”, voorheen werd dit “Hummingbird” genoemd, gepresenteerd. Met “Flutter for the Web” kan een Flutter app niet alleen naar iOS en Android worden gecompileerd, maar ook naar het web. Hier stopt het niet met Flutter. Het plan van Google is om Flutter apps overal te laten draaien o.a. Windows, macOS, Apple TV, Android TV noem maar op. Dus echt “build once, run anywhere”.
Tijdens de introductie van Flutter werd ook het Flare framework geïntroduceerd. Met Flare kunnen we, met behulp van de Flare webtool, een 2D Animated Vector Graphics maken. Met Flare kunnen we animaties maken, die we in ons Flutter project eenvoudig kunnen integreren. Het leuke aan Flare is dat dit volledig open source is. Ook de content die gemaakt wordt, is standaard open source. Het voordeel hiervan is dat veel animaties gratis beschikbaar zijn en te gebruiken zijn in je app. Wil je animaties voor jezelf houden, dan moet een klein bedrag worden betaald.
In het bovenstaande voorbeeld volgt de beer de cursor. Indien het password correct is ingevoerd en er op de “Sign In” button is gedrukt, dan zal de beer gaan lachen. Is het password incorrect, dan zal de beer met zijn hoofd “nee” schudden. Flare biedt dus de mogelijkheid om meerdere states vast te leggen in hun animatie en vervolgens van state 1 naar state 2 te animeren. Of van state 1 naar state 6 te animeren.
Naast Flare is ook de CI/CD tool CodeMagic geïntroduceerd. Met CodeMagic kan met enkele klikken een volledige build-straat worden ingericht. Zodra CodeMagic toegang krijgt tot het lezen van je repositories op GitHub, Bitbucket of GitLab zal CodeMagic op zoek gaan naar alle Flutter repositories waar je account toegang toe heeft. Na het vinden van de Flutter repositories krijg je de mogelijkheid deze te configureren voor het analyseren, bouwen, testen en uiteindelijk publiceren van de app in AppStore en/of PlayStore.
Naast een goed gedocumenteerde website heeft Flutter ook een heel leuk YouTube kanaal. “The Boring Flutter Development Show” is zeker een aanrader. In deze reeks van video’s laat het Flutter team -met veel humor- zien hoe je een app bouwt in Flutter. Ook de reeks “Widget of the week” is zeker de moeite waard. Zo ontdek je welke widgets er zijn en waarvoor ze gebruikt worden.
Android is gebouwd op de Linux kernel. Initieel is Android ontwikkeld voor digitale camera’s. De core van Android is eigenlijk niet gespecialiseerd in hetgeen we tegenwoordig allemaal van een telefoon verwachten. Dit is vaak de oorzaak dat hardware in Android telefoons minder presteert dan eigenlijk wordt verwacht. Android heeft OEM software, kernel en drivers die zo zijn geconfigureerd dat het niet eenvoudig is om alleen een kernel update uit te voeren. Je bent hiervoor afhankelijk van je telefoonleverancier. Dit alles maakt het niet een geweldig OS. Sinds 2016 is Google al bezig met een nieuw OS genaamd Fuchsia OS.
Fuchsia OS is gespecialiseerd in het draaien op zoveel mogelijk verschillende devices. Van koelkast tot verkeerslicht en van speaker tot telefoon. Google probeert hiermee één OS voor alles te maken. Fuchsia OS heeft zijn security beter op orde dan Android. Fuchsia OS is zo gebouwd dat een update op een eenvoudige manier door Google kan worden gepushed naar het device zonder tussenkomst van OEM. Het is nog niet duidelijk of Fuchsia OS ooit Android zal gaan vervangen. Een native Fuchsia OS app wordt gebouwd in Flutter.
Is Flutter de toekomst van de mobile app development? Door de goede documentatie en de plugins die voor een groot deel ook worden onderhouden door het Flutter team is dit zeker een framework waar we veel van zullen gaan horen. Niet alleen het gemak waarmee je een mooie interface kan bouwen, maar ook de tools die je tot je beschikking hebt voor het bouwen van een app, maakt Flutter tot een mooi framework.
Standaard is veel beschikbaar in het framework, waardoor je vaak zonder third party libraries een mooie app kan bouwen. Flutter is nog vrij nieuw, waardoor er weinig best practices zijn. Ook zijn er nog talloze bugs te vinden. Het is een levende community waar vragen gesteld kunnen worden en je ook snel antwoord krijgt. Mocht je een app willen bouwen, dan wil ik je zeker aanraden even te kijken naar de mogelijkheden van Flutter. Flutter is absoluut geen one-day-fly en is het overwegen waard als je de keus hebt een nieuwe app te bouwen, zelfs als dit maar voor één platform is.