Eine Beispielimplementierung zur Kommunikation zwischen einer Flutter-Applikation und einer GraphQL-Schnittstelle
Wer kennt es nicht? Es müssen Daten von einem Webservice beziehungsweise einer API abgerufen werden. Für eine solche entsprechende Kommunikation ist der Ansatz einer REST-Schnittstelle sehr weit verbreitet. Eine Alternative zum REST-Verfahren bietet GraphQL. Die von Facebook 2015 veröffentlichte Datenabfragesprache ermöglicht ebenfalls das Abrufen von Daten von einem Webservice. Mit Hilfe von GraphQL sollen folgende Punkte ermöglicht werden (https://graphql.org/):
- Eine vollständige und verständliche Beschreibung der Daten
- Abfrage der Daten, die wirklich benötigt werden → Bessere Strukturierung der Daten
- Erleichtert die Entwicklung der APIs (auch über einen längeren Zeitraum)
- Leistungsstarke Entwicklertools
Nun stellt sich die Frage, inwiefern eine Kommunikation innerhalb einer Flutter-Applikation mit einer GraphQL-Schnittstelle aussehen kann. Dafür wird als Beispiel-API die SpaceX GraphQL-API verwendet: https://studio.apollographql.com/public/SpaceX-pxxbxen/home?variant=current
GraphQL in Flutter – so setzen Sie die Schnittstellen-Kommunikation um
Zur Umsetzung der GraphQL-Schnittstellen-Kommunikation wird die graphql_flutter-Bibliothek verwendet: https://pub.dev/packages/graphql_flutter. Diese befindet sich derzeit bei der Version 5.1.0 und bietet viele verschiedene Features wie bspw. Pagination oder auch verschiedenen Cache Strategien. Im Nachfolgenden wird anhand eines simplen Beispiels veranschaulicht, inwiefern eine Kommunikation zu einer GraphQL-Schnittstelle in Flutter umgesetzt werden kann.
GraphQL in Flutter – ein Anwendungsbeispiel
In diesem Beispiel wird zur Verdeutlichung einer standardmäßigen Implementierung eine GraphQL-Schnittstelle verwendet, welche Daten von SpaceX offeriert (https://api.spacex.land/graphql/).
Wir wollen Daten von den Starts der Raketen abrufen. Dahingehend wird eine entsprechende GraphQL-Abfrage benötigt, welche diese Daten anfordert. Die genannte API ist sehr benutzerfreundlich und unterstützt den Developer bei Erstellung der Abfrage. Die Abfrage, die wir verwenden, sieht wie folgt aus:
Die gezeigte Query kann dann für das Bauen der eigentlichen Abfrage verwendet werden. Dafür werden im Widget-Tree der anzuzeigenden UI folgende Widgets genutzt:
Wie man hier sehen kann, wird im body das Query-Widget verwendet, welches als options-Parameter ein QueryOptions-Widget erhält. Innerhalb des QueryOptions-Widgets wird ein document-Parameter erwartet. Dort wird die vorher definierte Query, welche wir
als String definiert haben, übergeben. Des Weiteren sieht man hier das Festlegen der sogenannten fetchPolicy. Damit sind Cache-Strategien gemeint. In der Abbildung erkennt man noch den builder. Dort kann dann, sofern der Aufruf ausgeführt wurde, auf das Ergebnis des Aufrufs zugegriffen werden.
Ist der Aufruf noch nicht komplett ausgeführt worden, so wird ein zirkulärer Ladeindikator angezeigt. Dies kann man durch die Eigenschaft isLoading vom Ergebnis detektieren und entsprechend anzeigen. Sollte das Ergebnis des Aufrufs einen Fehler beinhalten, so kann dies mit dem Aufruf von hasException erkannt werden. Sofern dies zutrifft, wird lediglich ein Text mit der Problembeschreibung angezeigt. Sollte keiner der beiden Fälle zutreffen, so kann auf die Daten, in unserem Falle die Starts der Raketen von SpaceX, zugegriffen werden:
Das Zwischenlagern der Daten passiert in Zeile 38. Dort wird auf die Daten des Ergebnisses anhand des angegebenen Feldes zugegriffen. Da es mehrere Raketen-Starts gab, wird hierbei mit einer Liste gearbeitet. Diese kann dann wie gewohnt dem ListView-Builder übergeben werden. Für die ListView-Items wird ein Stack und entsprechende Sub-Widgets verwendet.
Unser Fachbereich Flutter stellt sich vor
Ausgehend vom backgroundImageWidget wird hinsichtlich der Liste ein zufälliges Bild ausgewählt, welches das Listitem dann darstellt. Das opacityLayerWidget wird verwendet, um das Bild zu schwärzen. Dadurch wird die Schrift auf dem Bild leichter lesbar (siehe Video der endgültigen App).
Zunächst einmal das Anzeigen des Bildes: Für eine visuelle Aufbereitung der Listitems werden lokale Bilder verwendet. Diese befinden sich in den assets des Projekts. Dafür existiert eine Liste als Konstante, welche die Bildernamen enthält:
Schlussendlich sollen noch ein paar Kennzahlen der jeweiligen Raketenstarts angezeigt werden. Dies geschieht in den folgenden Widgets:
Auf dem zufällig generierten Bild werden dann die folgenden Daten veranschaulicht:
- Missionsname
- Raketenname
- Gewicht
Final muss einmal die globale URL der API festgelegt und der Client definiert werden:
Der definierte Client wird dann im GraphQLProvider-Widget benutzt, welcher sich im MaterialApp-Widget befindet.
Die fertige Applikation sieht dann wie folgt aus:
Zusätzliche Anmerkungen zu GraphQL in Flutter
Das gezeigte Codebeispiel soll lediglich eine Implementierungsweise vorstellen, um Daten von einer GraphQL-Schnittstelle abrufen zu können. Allerdings bietet die graphql_flutter-Bibliothek weitere GraphQL-Spezifikationen an. Um Daten beispielsweise serverseitig zu modifizieren sind die sogenannten Mutations möglich. Zudem sind auch Subscriptions mit der Bibliothek umsetzbar, um kontinuierliche Updates von einer GraphQL-Schnittstelle zu erhalten. Weitere Spezifizierungen können unter https://pub.dev/packages/graphql_flutter nachgelesen werden.
Fazit
Abschließend kann gesagt werden, dass die graphql_flutter-Bibliothek ihren Zweck erfüllt und die Verwendung von GraphQL-APIs sehr einfach handhabbar umsetzt. Man muss lediglich die Basis-URL einmalig festlegen und kann dann über die GraphQL-Queries die Daten steuern, die entsprechend abgerufen und angezeigt werden sollen. Neben dem „standardmäßigen“ Abrufen der Daten bietet die Bibliothek wie beschrieben auch die weiteren GraphQL-Spezifikationen wie Mutations und Subscriptions an. Somit ist der wesentliche Funktionsumfang abgedeckt und ermöglicht das Verwenden von GraphQL-Schnittstellen in einer Flutter Applikation.