6. Flutter

6.1. Einführung

In unserem 6. und letzten Versuch haben wir eine kleine App-Anwendung mithilfe des Frameworks Flutter erstellt. Dies ist ein Open-Source-Framework von Google, das die Entwicklung plattformübergreifender mobiler Apps ermöglicht. Hiermit können Entwickler eine einzige Codebasis erstellen, die auf verschiedenen Plattformen wie Android, iOS, Web und Desktop ausgeführt werden kann. Als Programmiersprache wird Dart verwendet, wobei Flutter eine umfangreiche Sammlung von Widgets und Tools zur Erstellung von ansprechenden Benutzeroberflächen bietet.

Flutter logo

6.2. Warum Flutter?

  • Schnelle Entwicklung:

    Flutter ermöglicht eine schnelle und effiziente Entwicklung von Apps, da Änderungen sofort angezeigt werden können, ohne dass eine erneute Kompilierung erforderlich ist. Dies beschleunigt den Entwicklungszyklus erheblich.

  • Plattformübergreifend:

    Mit Flutter ist es möglich, eine einzige Codebasis zu verwenden, um Apps für verschiedene Plattformen zu erstellen. Dadurch können Entwickler Zeit und Ressourcen sparen, da sie nicht separate Apps für jede Plattform entwickeln müssen.

  • Ansprechende Benutzeroberflächen:

    Flutter bietet eine umfangreiche Sammlung von vorgefertigten Widgets, mit denen Entwickler ansprechende und benutzerfreundliche Benutzeroberflächen erstellen können. Zudem wird das sogenannte „Widget-Layout“ verwendet, das es ermöglicht, komplexe Benutzeroberflächen einfach zu erstellen und anzupassen.

  • Hohe Leistung:

    Flutter-Apps sind bekannt für ihre hohe Leistung. Durch die Verwendung der Dart-Programmiersprache und des Flutter-Frameworks können Apps direkt in Maschinencode kompiliert werden, was zu einer hohen Geschwindigkeit und Reaktionsfähigkeit führt.

  • Hervorragende Dokumentation und Community:

    Flutter verfügt über eine umfangreiche Dokumentation und eine aktive Entwicklergemeinschaft. Es gibt zahlreiche Ressourcen, Tutorials und Beispiele, die dabei helfen können, schnell mit der Flutter-Entwicklung zu beginnen und Probleme zu lösen.

6.3. Installation

  1. Installation der Flutter-SDK

  2. Extrahieren der SDK in einem bel. Verzeichnis

  3. flutter/bin zur Systemumgebungsvariable ‚PATH‘ hinzufügen

  4. Überprüfen der Installation über:

flutter doctor
  1. Installieren der Flutter-Erweiterung innerhalb der genutzten Entwicklungsumgebung

6.4. Erstellung einer Anwendung

Das Erstellen einer neuen Anwendung in einem bel. Verzeichnis funktioniert kinderleicht über folgenden Aufruf:

flutter create mein_projekt

Dadurch wird ein neues Flutter-Projekt namens „mein_projekt“ erstellt, welches default-mäßig Builds für android & ios ersellt. Als Parameter dieses create-Aufrufs kann man jedoch spezielle Plattformen definieren. Zusätzlich könnte man den Support für best. Plattformen auch konfigurieren.

# Definieren der Build-Plattformen
flutter create --platforms=windows,macos,linux,web,ios,android .

# Deaktivieren von ios-Support
flutter config --no-enable-ios

Der default-create Aufruf erzeugt folgende Struktur:

  mein_projekt/
├── android/
├── ios/
├── lib/
│   ├── main.dart
├── test/
├── .gitignore
├── .metadata
├── .packages
├── pubspec.lock
└── pubspec.yaml
  • android/:

    enthält das Android-Projekt der Flutter-App mit allen Android-spezifischen Dateien und Konfigurationen

  • ios/:

    enthält das ios-Projekt der Flutter-App mit allen ios-spezifischen Dateien und Konfigurationen

  • lib/:

    enthält den Großteil des Flutter-Quellcodes der App mit der Hauptdatei main.dart als Einstiegspunkt

  • test/:

    Verzeichnis für Unit-Tests

  • .gitignore:

    gibt an, welche Dateien und Verzeichnisse von der Versionskontrolle (z. B. Git) ignoriert werden sollten

  • .metadata:

    metadatenbezogene Informationen zum Projekt

  • .packages:

    Informationen über die Abhängigkeiten des Projekts

  • pubspec.lock:

    Informationen über die genauen Versionen der Abhängigkeiten

  • pubspec.yaml:

    YAML-Datei zur Angabe der Abhängigkeiten und Konfigurationen der Flutter-App

Nach der Erstellung der Anwendung kann man nun starten, die lib/main.dart-Datei zu bearbeiten. Diese dient, wie schon erwähnt, als Einstiegspunkt der App. Je nach Komplexität der App können Widgets, Benutzeroberflächenelemente oder Logik in verschiedenen Dateien und Verzeichnissen innerhalb lib/ organisiert werden.

Um die App nun auszuführen, verwendet man nachfolgenden Befehl:

flutter run

Dadurch wird die App auf einem Simulator (android/ios) oder einem angeschlossenem Endgerät bereitgestellt und gestartet.

6.5. Todo-Anwendung

Um die Möglichkeiten von Flutter zu demonstrieren, haben wir eine simple ToDo-Anwendung erstellt. Diese soll den Benutzern ermöglichen, ihre Aufgaben in verschiedenen ToDo-Listen zu organisieren.

Die Funktionsweise der App basiert auf einem Datenmodell und dessen Zustandsverwaltung.

Das Datenmodell wird durch die Klasse MyAppState repräsentiert, die eine Liste von Einträgen speichert. Jeder Eintrag ist wiederum eine Liste von Strings. Zusätzlich wird der aktuell ausgewählte Eintrag durch die Variable listId verfolgt. Die Klasse MyAppState erweitert das ChangeNotifier-Mixin, um Änderungen im Zustand zu verfolgen und Benachrichtigungen an die Benutzeroberfläche zu senden.

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.teal,
            brightness: Brightness.dark,
          ),
          useMaterial3: true,
        ),
        home: const ListPage(title: 'My Todo List'),
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {
  List<List<String>> entries = [
    <String>[
      'A',
      'B',
    ],
    <String>[
      'B',
      'D',
    ],
  ];
  int listId = 0;

  List<String> getEntries() {
    return entries[listId];
  }

  void remove(int elementIndex) {
    entries[listId].removeAt(elementIndex);
    notifyListeners();
  }

  void add(String element) {
    entries[listId].add(element);
    notifyListeners();
  }

  void addList() {
    entries.add(<String>[]);
    listId = entries.length - 1;
    notifyListeners();
  }

  void setListID(int id) {
    listId = id;
    notifyListeners();
  }
}

Die Benutzeroberfläche der App besteht aus mehreren Widgets, die in der build-Methode der Klasse ListPage definiert sind. Das Haupt-Widget ist ein Scaffold, das eine App-Leiste (AppBar), eine Navigationsleiste (NavigationRail), eine ToDo-Liste (TodoList) und einen FAB (FloatingActionButton) enthält.

Flutter logo

Die NavigationRail-Komponente ermöglicht es Benutzern, zwischen verschiedenen ToDo-Listen zu wechseln. Jede Liste wird durch ein Symbol repräsentiert. Beim Wechseln zwischen den Listen wird der listId-Wert in der MyAppState aktualisiert, was zu einer Aktualisierung der Benutzeroberfläche führt.

final List<IconData> menuIcons = const <IconData>[
    Icons.watch_later,
    Icons.home,
    Icons.hotel,
    Icons.paid,
    Icons.savings,
    Icons.pending_actions,
    Icons.liquor,
  ];

Das Hinzufügen und Entfernen von Einträgen wird durch den FloatingActionButton und die TodoList-Komponente ermöglicht. Durch Klicken auf den FAB wird ein Dialog geöffnet, in dem Benutzer neue Einträge für die aktuelle Liste eingeben können. Die eingegebenen Einträge werden zur Liste hinzugefügt, und die Benutzeroberfläche wird aktualisiert.

Flutter logo

Jeder Eintrag in der Liste kann durch Wischen nach links entfernt werden, was wiederrum zu einer Aktualisierung der Liste und der Benutzeroberfläche führt.

6.6. Fazit

Flutter erwies sich als effizientes Framework für die plattformübergreifende Entwicklung von App-Anwendungen. Durch dessen Verwendung konnten wir in recht kurzer Zeit eine reibungslos funktionierende App für iOS und Android erstellen, die ein ansprechendes Benutzererlebnis bietet.

Die Vorteile von Flutter, wie die Hot-Reload-Funktion für schnelle Entwicklungsiterationen und die umfangreiche Sammlung von Widgets, erleichterten uns die Erstellung einer modernen Benutzeroberfläche. Die Zustandsverwaltung mit Provider ermöglichte eine effektive Handhabung der App-Daten und eine reaktive Benutzeroberfläche.

Die klare Trennung von Datenmodell und Benutzeroberfläche in der Architektur des Projekts erleichterte die Wartung des Codes und die Zusammenarbeit im Team. Insgesamt sind wir mit dem Ergebnis unserer Arbeit zufrieden und sehen großes Potenzial für zukünftige Projekte mit Flutter.

6.7. Quellen

https://docs.flutter.dev https://de.wikipedia.org/wiki/Flutter_(Software) https://api.flutter.dev/index.html https://codelabs.developers.google.com/codelabs/flutter-codelab-first#0