maandag 5 juni 2023

Flutter is een leuk framework


Flutter is een framwork dat kan worden gebruikt om cross platform apps te maken. Ik heb het recentelijk geleerd om mijn app "Voorlees-papegaai Jacky" te maken. 

Flutter kan ook gebruikt worden om desktop apps en websites te maken, maar tot nu toe heb ik het gebruikt om voor Android en iOS te ontwikkelen. Dit zijn mijn ervaringen.

Frameworks die ik al eerder heb gebruikt

Voordat ik Flutter koos voor mijn volgende project waren en de nodige twijfels. Ik ben al bekend met Cordova en Xamarin. Het is al een tijdje geleden sinds ik nog een mobiele app heb gemaakt. De opkomst van ReactNative heb ik compleet gemist. En nu zijn er zelfs nog meer moderne opties buiten ReactNative. 

Dus zou ik een framework gebruiken waarmee ik al bekend ben? Iets nieuws proberen? Ionic lijkt op Cordova. Ik heb goede dingen gehoord over ReactNative. En er is nu ook iets wat Flutter heet?

Ik koos voor Flutter. Het leek me een goed idee iets nieuws te leren, om te zien wat een nieuwer framework te bieden heeft ten opzichte van een bestaand framework.

De keuze was niet makkelijk, het kwam aan op een tie-breaker. Ik koos uiteindelijk voor Flutter omdat het dan gaat om een strongly typed taal, voor mij is dit een voordeel. (Dit is natuurlijk heel subjectief.)

Flutter hello world

De app die ik wil maken speelt een geluidseffect af op basis van wat je voorleest. Je kan deze app bijvoorbeeld gebruiken terwijl je voor je kinderen 's avonds voorleest. Je hebt er misschien al van gehoord.

Maar eerst heb ik een "hello world" app gemaak met slechts één knop en een tekstveld die een teller weergeeft.

Wanneer je een nieuw Flutter project start, dan heb je een main.dart file, en nog wat projectfiles zoals Gradle build scripts. Dart is de programmeertaal die wordt gebruikt om Flutter apps te maken, meer hierover later.

Er zijn drie elementen in main.dart:

  • Een main functie. Dit geeft mij al een goede indruk. Het hebben van een simpele main functie terwijl je een mobiele app maakt. Waarom niet eigenlijk?
  • Een "MyApp" class die een Stateless Widget voorstelt. Ieder GUI element is een widget in Flutter, dus de top-level app is dat ook.
  • Een Stateful Widget genaamd “ReadingParrot” in mijn geval. Een stateful widget is altijd gekoppeld aan bijvoorbeed een _ReadingParrotState class. Het is een stateful widget omdat het zijn uitzicht en gedrag veranderd naargelang de waardes in zijn state.

Gebruikmakend van de getting started documentatie van Flutter, was het opzetten van de hello world app een vlot proces.

Het maken van de Voorlees-papegaai GUI

De GUI had ik reeds ontworpen, en nu zou ik die willen implementeren in Flutter

Een screenshot van een vroege versie van de voorlees-papegaai Jacky app.

Hier is nog een groot voordeel van Flutter als je het mij vraagt: de GUI en de back-end logica worden opgemaakt in dezelfde taal: Dart. Je kan alles in dezelfde file stoppen, als je dat wilt.

Je definieert een GUI in Dart, wat neerkomt op een geneste declaratie van variabelen. Variabelen zouden zijn van het type Row of Column voor layout-ing, Button, Text, Icon,… En wanneer je een button object instantieert, dan geef je Dart closures door aan de "on call" property om gedrag toe te voegen.

Variabelen nesten om een GUI te bouwen geeft een indruk dat het niet goed zou schalen. Daar een een mooie oplossing voor: zet code die de GUI opbouwt in hun eigen functies, duh. Maar even serieus, in de praktijk is er kans dat het nesten van meer en meer variabelen, naargelang dat de GUI complexer wordt, uit de hand zou kunnen lopen. Mijn tip hier is om aparte functies te maken wanneer mogelijk, refactoring wordt zelden nog gedaan achteraf. (Dit is van toepassing op eender welk software project als je het mij vraagt.)

Een kleine klacht die ik heb, om de bovenstaande opvattingen te balanceren: het zetten van marges lijkt niet erg intuïtief te zijn. Je zou regelmatig marges en padding toevoegen aan containers. De Container widget heeft een margin veld, maar hier geef je niet direct numerieke waardes in. Je moet een EdgeInsets object instantiëren. De naam EdgeInsets geeft niet echt aan "gebruik dit voor het zetten van marges en padding". Er zijn meerdere voorbeelden hiervan, maar alles kon opgelost worden met een snelle Google search.

Plugins!

Wat is een goed framework zonder plugins? Zelfs Cordova heeft ze.

Plugins laten toe om bepaalde zaken platform onafhankelijk te gebruiken, je wil liefst geen code schrijven voor een specifiek platform.

Mijn voorlees-papegaai zou nodig hebben:

  • Spraakherkenning: er is een plugin ✅.
  • Audio playback: er is een plugin ✅.
  • Internet connectiviteit checks: Er is een plugin ✅.

Een plugin installeren kan worden gedaan via het commando:  flutter pub add <plugin>. Of je  kan een statement toevoegen aan pubspec.yaml En dan het commando: flutter pub get uitvoeren.

Geen verder commentaar nodig hier, de plugins die ik nodig heb zijn beschikbaar en zijn makkelijk te installeren. 

GUI performance

Een Flutter ontwikkelaar heeft goede controle over wanneer er een GUI display update moet plaatsvinden.

Herinner je het stateful widget concept wat eerder was vermeld, wanneer er iets verandert in het bijhorende _state object, dan moet je setState() aanroepen om aan te geven dat een GUI update noodzakelijk is. Dat moet je inderdaad, want anders verandert er niks op het scherm. Dit geeft je complete controle wat dat betreft, dit is zeker een voordeel de manier waarop ik dit bekijk.

Nog een interessant concept dat ik heb moeten toepassen in mijn voorlees-papegaai app: het selectief updaten van de GUI, i.e. setState() aanroepen voor een subset van de GUI. Ik wil live het microfoon volume tonen in de GUI, maar ik wil niet steeds de gehele GUI opbouwen voor iedere volume update, waarvan er erg veel plaatsvinden. Zonder teveel in detail te gaan, dit is ondersteund in Flutter.

Flutter GUI profiling is netjes geïntegreerd in Android Studio. Ik kon bevestigen dat het selectief updaten, zoals in de vorige paragraaf is vermeld, werkt zoals verwacht.

Over Android Studio gesproken...

Flutter ontwikkeling in Android Studio

Het Flutter framework is goed geïntegreerd in Android Studio. Dit zijn enkele features:

  • GUI profiling integratie, zoals eerder vermeld.
  • Hints over Dart conventies, die meestal automatisch toegepast kunnen worden. Dit is een enorme hulp om goede gewoontes te kweken bij beginners.
  • Een hot-reload/hot-restart knop. Dit is een geweldige feature van Flutter in het algemeen,  wijzigingen toepassen in Dart code duurt milliseconden om met een echt Android apparaat te synchroniseren.

Het is bijna saai, bijna. Maar hier heb ik verder ook geen commentaar op. Flutter ontwikkeling in Android Studio gaat mij goed af.

De Dart programmeertaal

Dart is single-threaded, asynchroon en strongly-typed. Het feit dat het single-threaded is houdt dingen simpel, terwijl het asynchrone aspect (het heeft async/await mechanismen) het makkelijk maakt om het renderen van de GUI niet te blokkeren met andere langdurige taken.

Hier zijn wat technische details over de programmeertaal:

  • Het is een strongly typed taal, wat de ontwikkeling minder foutgevoelig maakt. Er is ook type deduction, je kan gewoon final x = calcX() intypen bijvoorbeeld.
  • Het ondersteund runtime en static constanten, beide worden gecheckt tijdens compilatie.
  • Dart gaat goed om met null safety. Je kan een type nullable declareren, en je moet een check doen vooraleer je het object mag gebruiken, anders krijg je een compiler error. Wanneer je een nullcheck doet dan wordt meestal die variabele automatisch "gepromoveerd" naar een niet-nullable type.

Het biedt echter geen nieuwe concepten aan vergeleken met bestaande programmeertalen. Dart is desondanks een degelijke taal. Maar ik vind het vreemd dat een framework wordt gebouwd op een minder bekende taal, die aan de oppervlakte conceptueel hetzelfde is als bestaande talen. Dat verhoogt zeker en vast de leercurve, je moet zowel een framework als een taal leren, want de Dart taal wordt nagenoeg nergens anders dan voor Flutter gebruikt. Maar aan het einde van de dag is een programmeertaal slechts een werkmiddel.

De Flutter FAQ verklaart waarom het voor Dart koos. De vermeldde criteria gaan blijkbaar niet over de populariteit van de taal, het gaat meer om de technische verdienste van de taal zelf.

Ik vind dat Dart wel wat lijkt op Kotlin op veel manieren. Dart komt bij mij over als een soort "Kotlin light". Als je ervaring met Kotlin hebt, dan zou dat wellicht enigszins van pas komen bij Dart.

Conclusie

Ik zou Flutter iedereen aanraden die op zoek is naar iets nieuws om te leren.

Vergeleken met de frameworks die ik al kende, biedt Flutter eenvoud door de ontwikkelaar de GUI en het gedrag te laten maken in dezelfde taal. Het biedt ook moderne features aan zoals hot-reload/hot-restart.

Dat gezegd hebbende, zowel een nieuw framework leren als een nieuwe programmeertaal tegelijk is intimiderend. Voor mij was het desondanks de moeite waard. Ik heb er een mooie app mee kunnen maken al zeg ik het zelf.

Het kan trouwens ook gebruikt worden voor website en desktop ontwikkeling. Dit framework leren biedt veel mogelijkheden.

Bedankt voor het lezen van mijn gedachten en indrukken over het Flutter framework. Ik hoop dat het voor jou van pas zal komen!