Unser erstes Flutter-Projekt verstehen

In der letzten Lektion haben wir unser erstes Flutter-Projekt erstellt. Es ist sehr einfach und enthält nur einen Button, der bei Klick eine Zahl hochzählt. Unten sehen Sie die Verzeichnisstruktur dieses Projekts.

Projektverzeichnis

Sie sehen viele Ordner und Dateien wie android, web, windows, lib, test und mehr. Wo schreiben wir den Quellcode? Im android-Ordner? Im windows-Ordner? Tatsächlich nicht – der Quellcode liegt im lib-Ordner. Öffnen Sie lib, dort befindet sich die Datei main.dart.

Dieser lib-Ordner speichert künftig Ihren gesamten Quellcode. Sie programmieren in Dart, nicht in Java oder C++. Flutter nutzt die Sprache Dart. Warum gibt es aber Ordner wie android, web und windows im Projektstamm?

Das ist leicht verständlich: Flutter kann für verschiedene Plattformen kompiliert werden, genau durch diese Ordner.

Flutter ist ein Framework nach dem Prinzip ein Dart-Code für mehrere Plattformen. Der Ordner lib enthält den plattformübergreifenden gemeinsamen Business-Code, den Sie schreiben. Die Ordner android / windows / web / macos / linux sind dagegen native Host-Projekte für jede Plattform, die den Flutter-Rendering-Engine in das jeweilige Betriebssystem einbetten und ausführen lassen.

1. Ordner android

Dies ist das native Projekt für die Android-Plattform

Es stellt die Ausführungsumgebung für Android-Apps bereit und beherbergt die Flutter-Rendering-Engine. Alle tiefgreifenden Android-Einstellungen werden hier konfiguriert: App-Berechtigungen, Icons, Paketnamen und mehr. Hier können Sie Android-spezifische Einstellungen vornehmen sowie native System-APIs aufrufen (Kamera, Bluetooth, Benachrichtigungen, Standort usw.)

2. Ordner windows

Dies ist das native Projekt für Windows-Desktop-Anwendungen

Es handelt sich um ein natives C++ Win32-Projekt, das Windows-Fenster erstellt und die Skia-Grafikengine initialisiert. Skia ist eine Grafikbibliothek von Google, mit der Flutter Fenster und alle Steuerelemente von Desktop-Apps rendert.

Im windows-Verzeichnis liegen alle tiefgreifenden Einstellungen für Windows-Desktop-Software: Fenstergröße, Titelleiste, Icons, System-Tray (das Symbol unten rechts in Windows).

Später können Sie das Projekt als exe oder msix verpacken und im Microsoft Store veröffentlichen.

3. Ordner web

Statisches Webseiten-Projekt (HTML/JS/CSS) mit dem Web-Einstiegspunkt index.html. Ihr Dart-Quellcode wird schließlich zu Web-Ressourcen kompiliert.

Sie können Seitentitel, Icons, statische Ressourcen und Routen konfigurieren. Bei der Kompilierung entstehen HTML/CSS/JS-Dateien, die auf einen Server hochgeladen und im Browser geöffnet werden können.

Weitere Ordner

Wir verwenden hier kein iOS, macOS und Linux, weil wir diese Optionen bei der Projekterstellung nicht markiert haben – diese Ordner fehlen daher. Ihre Funktionsweise ist aber identisch.

ios: Natives Xcode-Projekt für Apple iOS, zum Verpacken von IPA-Dateien und Veröffentlichung auf iPhone

macos: Natives Cocoa-Desktop-Projekt für macOS, Client für Mac-Computer

linux: Linux-Desktop-Projekt auf GTK-Basis

Oben rechts in Android Studio wählen Sie verschiedene Plattformen aus, um unterschiedliche App-Versionen zu kompilieren. Sie können auch direkt die Kommandozeile nutzen. Wenn Sie eine Plattform auswählen und den grünen Dreieck-Button in Android Studio klicken, werden im Hintergrund Flutter-Befehle ausgeführt.

# Android starten, liest Einstellungen aus dem android-Ordner
flutter run -d android

# Windows-Desktop starten, liest das C++-Projekt aus dem windows-Ordner
flutter run -d windows

# Web-Version starten, liest die HTML-Datei aus dem web-Ordner
flutter run -d chromeCode-Sprache: PHP (php)

Öffnen Sie die Datei runner / main.cpp im windows-Ordner

#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>

#include "flutter_window.h"
#include "utils.h"

int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
                      _In_ wchar_t *command_line, _In_ int show_command) {
  // Attach to console when present (e.g., 'flutter run') or create a
  // new console when running with a debugger.
  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
    CreateAndAttachConsole();
  }

  // Initialize COM, so that it is available for use in the library and/or
  // plugins.
  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

  flutter::DartProject project(L"data");

  std::vector<std::string> command_line_arguments =
      GetCommandLineArguments();

  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));

  FlutterWindow window(project);
  Win32Window::Point origin(10, 10);
  Win32Window::Size size(1280, 720);
  if (!window.Create(L"myproject", origin, size)) {
    return EXIT_FAILURE;
  }
  window.SetQuitOnClose(true);

  ::MSG msg;
  while (::GetMessage(&msg, nullptr, 0, 0)) {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
  }

  ::CoUninitialize();
  return EXIT_SUCCESS;
}
Code-Sprache: PHP (php)

Wenn Sie für Windows Desktop kompilieren, ist diese main.cpp der echte Einstiegspunkt des Programms: zuerst wird diese C++-Datei ausgeführt, danach geht die Steuerung an Ihre lib/main.dart.

Gleichermaßen sehen Sie beim Öffnen des android-Ordners eine Struktur, die nahezu identisch mit Android-Projekten ist, die mit Kotlin oder Java entwickelt werden.

Dort finden Sie ebenfalls den src-Ordner, die Datei AndroidManifest.xml, MainActivity und weitere Elemente, die jedem Android-Entwickler vertraut sind. Tatsächlich beginnt der Ablauf einer mit Flutter erstellten Android-App in diesem android-Ordner.

Öffnen Sie außerdem den web-Ordner – dort finden Sie den Web-Einstiegspunkt index.html

Dart-Dateien

Die Datei main.dart im lib-Ordner wird künftig der zentrale Ort Ihrer Entwicklung sein. Sie können Unterordner erstellen und weitere Dart-Dateien innerhalb von lib hinzufügen.

Öffnen Sie main.dart

// Einbinden der Material-Komponentenbibliothek
import 'package:flutter/material.dart';

// Programmeinstiegsfunktion
void main() {
  runApp(const MyApp());
}

// Wurzelkomponente der App (zustandslos)
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      // Globale Theme-Einstellungen
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      // Startseite
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

// Startseite (zustandsbehaftete Komponente)
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // Parameter für den Seitentitel
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

// Klasse zur Verwaltung des Zustands der Startseite
class _MyHomePageState extends State<MyHomePage> {
  // Zählervariable
  int _counter = 0;

  // Methode zum Hochzählen des Zählers
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // Grundgerüst für das Seitenlayout
    return Scaffold(
      // Obere Navigationsleiste
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      // Hauptinhalt der Seite
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter', // Zeigt die numerische Variable an
              style: Theme.of(context).textTheme.headlineMedium, // Textstil
            ),
          ],
        ),
      ),
      // Schwebender Button unten rechts: onPressed führt _incrementCounter aus, tooltip ist der Hilfetext, child legt das Icon fest
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}Code-Sprache: JavaScript (javascript)

1. Einstiegsteil

import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}
Code-Sprache: JavaScript (javascript)
  • Bindet Material ein, die offizielle UI-Komponenten-Sammlung von Google (Buttons, Seiten, Texte usw.). Apple hat ein eigenes UI-Framework.
  • main ist der einzige Einstiegspunkt eines Dart-Programms; runApp() startet die App und hängt die Wurzelkomponente MyApp an

2. MyApp: Globale Wurzelkomponente

Sie ist ein StatelessWidget (zustandsloser Widget), wir erklären das später detailliert, merken Sie sich dies vorerst einfach.

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

  // Wurzelkomponente Ihrer Anwendung
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
Code-Sprache: JavaScript (javascript)
  • Globale Einstellungen: App-Name, allgemeines Theme, Standard-Startseite
  • MaterialApp: Hülle für Apps im Material-Stil, verwaltet Routen, Themes und Titel zentral
  • home legt die Seite fest, die beim Start der App geöffnet wird: MyHomePage

3. MyHomePage: Startseite

Die Seite, die standardmäßig beim Öffnen des Fensters oder der App angezeigt wird. Es handelt sich um ein StatefulWidget (zustandsbehaftetes Widget), dazu kommen später ausführliche Erläuterungen.

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}Code-Sprache: JavaScript (javascript)
  • Sie enthält veränderbare Daten (die Zählerzahl), daher wird ein zustandsbehaftetes Widget verwendet
  • Erhält den Titelparameter title von außen, innerhalb der Zustandsklasse lesbar über widget.title
  • Muss mit einer passenden Klasse _MyHomePageState kombiniert werden, die Seitenvariablen und Interaktionslogik speichert

4. _MyHomePageState

Klasse für die Zustandslogik, zuständig für die Verarbeitung von Seitenlogik, Darstellung und Aktualisierung der Benutzeroberfläche

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        backgroundColor: Theme.of(context).colorScheme.inversePrimary,

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}Code-Sprache: JavaScript (javascript)
  1. int _counter = 0: Veränderbare Seitendaten – der Zählerwert
  2. _incrementCounter(): Ereignis bei Klick auf den Button
    • setState() teilt Flutter mit, dass sich Daten geändert haben, die UI der Seite neu gezeichnet werden muss
    • Erhöht den Zähler um 1
  3. build(): Wird bei jeder Aktualisierung ausgeführt und gibt das gesamte Seitenlayout zurück

5. Scaffold: Seitengerüst

Layout-Vorlage für eine Seite, gehört zur Klasse _MyHomePageState

  • appBar: Obere Titelleiste
  • body: Hauptinhalt der Seite
    • Center zentriert Elemente, Column ordnet Texte vertikal an
  • floatingActionButton: Runder Plus-Button unten rechts, verknüpft mit der Hochzählmethode bei Klick

Gesamter Ausführungsablauf

  1. Programmstart → Ausführung von main → Laden von MyApp
  2. MyApp rendert MaterialApp → Lädt die Startseite MyHomePage
  3. Die Seite rendert Titelleiste, zentrierten Text und Plus-Button
  4. Klick auf den Button → Ausführung von _incrementCounter + setState zeichnet die Seite neu → Zahl wird aktualisiert

Unser erstes Flutter-Projekt verstehen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert