ein buntes Themenspektrum

Schlagwort: Dart

Deine Flutter Wetter-App: Schritt für Schritt – Teil 6

Teil 6: Grünland im Blick – Die Grünlandtemperatursumme (GTS) berechnen und anzeigen

Hallo und herzlich willkommen zum sechsten und vorerst letzten Teil unserer Kernserie zur Flutter Wetter-App!

In den vorherigen Teilen haben wir eine Menge geschafft: von der Anzeige der aktuellen Temperatur über die Adresssuche bis hin zur Visualisierung des Temperaturverlaufs als Diagramm. Unsere App wird immer nützlicher!

Heute krönen wir das Ganze mit einer Spezialfunktion: der Berechnung und Anzeige der Grünlandtemperatursumme (GTS). Dieser agrarmeteorologische Wert ist besonders für Landwirte und Gärtner interessant, da er Aufschluss über den Vegetationsbeginn im Frühjahr gibt. Aber auch für Naturinteressierte ist es eine spannende Ergänzung.

Das Ziel für heute:

  • Wir verstehen, was die Grünlandtemperatursumme ist und wie sie berechnet wird.
  • Wir lernen, wie man historische Wetterdaten von einem anderen Endpunkt der Open-Meteo API (der Archiv-API) abruft.
  • Wir implementieren die Berechnungslogik für die GTS, inklusive der Monatsfaktoren.
  • Wir integrieren einen Caching-Mechanismus, um nicht bei jedem App-Start die gesamten historischen Daten neu laden zu müssen.
  • Wir erstellen ein neues Widget, um die GTS ansprechend darzustellen.

Warum GTS?

Die GTS ist ein gutes Beispiel dafür, wie man mit Flutter und externen APIs auch spezifischere, fachliche Anforderungen umsetzen kann. Es erfordert Datenabruf, Datenverarbeitung und eine klare Logik.

Schritt 1: Den Code für Teil 6 holen

Wie immer findest du den Code für diesen Teil im Git-Repository.

  1. Öffne ein Terminal in deinem Projektordner (flutter_weather_app_blog).
  2. Sichere lokale Änderungen, falls vorhanden.
  3. Wechsle zum main-Branch und aktualisiere:
    git checkout main
    git pull origin main

  4. Checke den Code-Stand für Teil 6 aus: (Tag-Name ggf. anpassen)
    git checkout part6-gts-calculation

  5. Abhängigkeiten holen & Code generieren:
    flutter pub get

    dart run build_runner build --delete-conflicting-outputs

Öffne das Projekt in VS Code.

Schritt 2: Was ist die Grünlandtemperatursumme (GTS)?

Die GTS ist die Summe der positiven Tagesmitteltemperaturen (oberhalb von 0°C), die ab Jahresbeginn anfallen. Dabei werden die Werte im Januar mit dem Faktor 0,5 und im Februar mit 0,75 gewichtet. Ab März zählt jeder positive Tagesmittelwert voll (Faktor 1,0). Ein bestimmter Schwellenwert der GTS (oft um 200 °Cd – Grad Celsius Tage) signalisiert den nachhaltigen Beginn der Vegetationsperiode.

Berechnung: GTS = Σ (Tagesmittel – 0°C) * Monatsfaktor (Nur für Tage mit Tagesmittel > 0°C)

Schritt 3: Die Datenquelle – Open-Meteo Archiv-API

Um die GTS zu berechnen, benötigen wir die täglichen Durchschnittstemperaturen seit dem 1. Januar des aktuellen Jahres. Die normale Forecast-API von Open-Meteo liefert historische Daten nur für einen begrenzten Zeitraum (z.B. die letzten 7-90 Tage). Für längere historische Zeitreihen bietet Open-Meteo eine separate Archiv-API.

  • Neue API-Endpunkte (lib/src/core/constants/app_constants.dart):
    • Wir haben Konstanten für die Basis-URL und den Endpunkt der Archiv-API hinzugefügt:
      static const String openMeteoArchiveApiBaseUrl = 'archive-api.open-meteo.com';
      static const String openMeteoArchiveEndpoint = '/v1/archive';

  • Parameter für GTS (lib/src/core/constants/app_constants.dart):
    • Ebenfalls neu sind die Konstanten für die GTS-Berechnung selbst:
      static const double gtsBaseTemperature = 0.0;
      static const Map<int, double> gtsMonthlyFactors = {1: 0.5, 2: 0.75};
      static const int gtsLocationCachePrecision = 2; // Für Caching

Schritt 4: Datenmodelle für historische Daten (data Layer Models)

Die Archiv-API liefert tägliche Daten in einer ähnlichen, aber doch eigenen Struktur. Daher brauchen wir neue Modelle:

  • lib/src/features/weather/data/models/daily_units_model.dart (NEU): Analog zum HourlyUnitsModel, aber für tägliche Daten (z.B. Einheit für temperature_2m_mean).
  • lib/src/features/weather/data/models/daily_data_model.dart (NEU): Bildet das daily-Objekt der Archiv-API ab. Enthält Listen für time (Datum-Strings) und temperature_2m_mean (tägliche Durchschnittstemperaturen). Die fromJson-Methode parst diese in DateTime– und double-Listen.
  • lib/src/features/weather/data/models/historical_response_model.dart (NEU): Das Gesamtmodell für die Antwort der Archiv-API, analog zum ForecastResponseModel.

Schritt 5: API-Service erweitern (data Layer Datasource)

Der WeatherApiService (lib/src/features/weather/data/datasources/weather_api_service.dart) wurde um eine Methode zum Abruf der historischen Daten erweitert:

  • getHistoricalDailyTemperatures (NEUE Methode):
    • Nimmt latitude, longitude, startDate und endDate als Parameter.
    • Baut die URL für den Archiv-API-Endpunkt (aus AppConstants).
    • Fordert daily=temperature_2m_mean an.
    • Parst die JSON-Antwort mithilfe des neuen HistoricalResponseModel.
    • Enthält robustes Error-Handling, ähnlich wie getForecastWeather.

Schritt 6: Der GTS-Berechnungsservice (application Layer)

Die eigentliche Logik zur Berechnung der GTS und das Caching der dafür benötigten Daten haben wir in einen neuen Service ausgelagert:

  • lib/src/features/weather/application/gts_calculator_service.dart (NEU):
    • Riverpod Provider: Wird über @riverpod bereitgestellt (gtsCalculatorServiceProvider) und bekommt den WeatherApiService injiziert.
    • Caching: Implementiert einen einfachen In-Memory-Cache (_historicalDataCache, _forecastForGtsCache).
      • _getLocationCacheKey: Erstellt einen eindeutigen Schlüssel für den Cache basierend auf gerundeten Koordinaten (um Ungenauigkeiten durch GPS zu minimieren).
      • Vor einem API-Aufruf wird geprüft, ob gültige Daten im Cache vorhanden sind (_cacheDuration).
    • calculateGtsForLocation(LocationInfo location) Methode:
      1. Cache-Prüfung: Versucht, historische Tagesmittelwerte aus dem Cache zu laden.
      2. API-Abruf (historisch): Wenn nicht im Cache, ruft es _apiService.getHistoricalDailyTemperatures auf, um die Tagesmittelwerte vom 1. Januar bis gestern zu holen. Speichert das Ergebnis im Cache.
      3. Datenaufbereitung: Die erhaltenen Daten werden in einer Map<DateTime, double> (Datum -> Temperatur) gespeichert.
      4. Forecast-Ergänzung (Lücke füllen): Die Archiv-API liefert oft Daten nur bis zum Vortag. Wenn die letzten Tage des aktuellen Jahres fehlen, um bis „gestern“ zu kommen (z.B. weil die Archivdaten noch nicht aktualisiert sind), versucht der Service, diese Lücke mit stündlichen Daten aus der Forecast-API zu füllen.
        • Dafür wird _apiService.getForecastWeather mit past_days (um die Lücke abzudecken) und forecast_days: 0 aufgerufen.
        • Aus den stündlichen Forecast-Daten werden dann Tagesmittelwerte für die fehlenden Tage berechnet und zu den dailyAverages hinzugefügt. Auch diese Forecast-Daten werden gecacht.
      5. GTS-Summation: Iteriert durch alle Tage des aktuellen Jahres (bis gestern) in der dailyAverages-Map.
        • Wenn die Tagesmitteltemperatur > gtsBaseTemperature (0°C) ist:
        • Der entsprechende gtsMonthlyFactor (Jan: 0.5, Feb: 0.75, sonst 1.0) wird angewendet.
        • Der Beitrag des Tages (Tagesmittel - Basis) * Faktor wird zur Gesamtsumme addiert.
      6. Gibt die berechnete gtsSum zurück.
    • Fehlerbehandlung: Wirft GtsCalculationException bei Problemen.

Schritt 7: Datenmodell und Repository anpassen (domain & data Layer)

  • WeatherData Entität (lib/src/features/weather/domain/entities/weather_data.dart):
    • Wurde um das Feld final double greenlandTemperatureSum; erweitert.
    • Die empty und copyWith Methoden wurden angepasst.
  • WeatherRepositoryImpl (lib/src/features/weather/data/repositories/weather_repository_impl.dart):
    • Abhängigkeit: Bekommt jetzt den GtsCalculatorService über den Konstruktor injiziert (dank Riverpod).
    • getWeatherForLocation-Methode:
      • Startet den Aufruf von _apiService.getForecastWeather() (für aktuelle und stündliche Daten) und _gtsCalculatorService.calculateGtsForLocation() parallel mit Futures.
      • Wartet mit await auf beide Ergebnisse.
      • Fängt Fehler von calculateGtsForLocation ab und gibt in diesem Fall double.nan für die GTS zurück, damit der Rest der Wetterdaten trotzdem angezeigt werden kann.
      • Fügt den erhaltenen gtsValue beim Erstellen des WeatherData-Objekts hinzu.
      • Kann jetzt auch GtsCalculationException fangen und in GtsFailure umwandeln.

Schritt 8: Anzeige der GTS (presentation Layer)

  • lib/src/features/weather/presentation/widgets/gts_display.dart (NEU):
    • Ein neues StatelessWidget, das den gtsValue als Parameter erhält.
    • Stellt die GTS in einer Card ansprechend dar, inklusive Icon und Einheit (°Cd).
    • Zeigt „–“ an, wenn der gtsValue double.nan ist (also ein Fehler bei der Berechnung auftrat).
  • lib/src/features/weather/presentation/screens/weather_screen.dart:
    • In der _buildSuccessContent-Methode wird nun das neue GtsDisplay-Widget hinzugefügt und bekommt data.greenlandTemperatureSum übergeben. Es wird zwischen der aktuellen Temperaturanzeige und dem Diagramm platziert.

Schritt 9: Änderungen am State Management (application Layer)

Überraschenderweise sind hier keine Änderungen im WeatherState oder WeatherNotifier direkt nötig!

  • Der WeatherState verwendet bereits das WeatherData-Objekt, das nun das greenlandTemperatureSum-Feld enthält.
  • Der WeatherNotifier ruft das WeatherRepository auf, das nun ein WeatherData-Objekt mit befüllter GTS zurückliefert. Der Notifier reicht dieses Objekt einfach an den State weiter.

Das ist ein weiterer Beleg für die Vorteile einer guten Entkopplung: Die UI und der State-Notifier müssen die Details der GTS-Berechnung nicht kennen.

Schritt 10: Ausführen und Testen!

Starte die App (F5):

  1. Lade das Wetter für einen Ort (GPS oder Suche).
  2. Unter der aktuellen Temperatur und vor dem Diagramm sollte nun eine neue Karte mit der Grünlandtemperatursumme erscheinen.
  3. Beobachte die Logs: Du solltest sehen, wie der GtsCalculatorService arbeitet, historische und ggf. Forecast-Daten für die Ergänzung abruft. Beim zweiten Laden für denselben Ort (innerhalb der Cache-Dauer) sollten die Daten schneller aus dem Cache kommen.
  4. Vergleich (optional): Wenn du Zugang zu offiziellen GTS-Werten für deinen Ort hast, kannst du versuchen, die Ergebnisse zu vergleichen. Beachte, dass es leichte Abweichungen geben kann, je nach genauer Datenquelle und Methodik der offiziellen Stellen.

Fazit und Abschluss der Kernserie

Herzlichen Glückwunsch! Du hast die Grünlandtemperatursumme erfolgreich in deine Wetter-App integriert. Damit haben wir alle Kernfunktionen umgesetzt, die wir uns am Anfang vorgenommen hatten.

In diesem Teil hast du gelernt:

  • Wie man Daten von einem anderen API-Endpunkt (Archiv-API) abruft.
  • Wie man historische Daten verarbeitet.
  • Wie man eine spezifische fachliche Berechnung (GTS mit Monatsfaktoren) implementiert.
  • Wie man einen einfachen In-Memory-Cache erstellt und nutzt, um API-Anfragen zu reduzieren.
  • Wie man Daten aus verschiedenen Quellen (historisch, Forecast) kombiniert, um ein vollständiges Bild zu erhalten.
  • Wie eine gut strukturierte App das Hinzufügen komplexer Logik erleichtert, ohne dass alle Teile der App angepasst werden müssen.

Unsere Wetter-App ist nun ein ziemlich umfassendes Projekt, das viele Aspekte der Flutter-Entwicklung abdeckt. Du hast eine solide Grundlage geschaffen, auf der du aufbauen und weitere Ideen umsetzen kannst!

Wie geht es weiter?

Das war das Ende der geplanten Kernfunktionen. Aber eine App ist selten „fertig“. Mögliche nächste Schritte könnten sein:

  • UI-Verfeinerungen: Icons für Wetterbedingungen, schönere Übergänge, Anpassung an verschiedene Bildschirmgrößen.
  • Weitere Wetterdaten: Windgeschwindigkeit, Luftfeuchtigkeit, Sonnenaufgang/-untergang.
  • Einstellungen: Wahl der Temperatureinheit (Celsius/Fahrenheit), Anpassung der Diagramm-Optik.
  • Caching verbessern: Persistenter Cache (z.B. mit shared_preferences oder einer lokalen Datenbank).
  • Testing vertiefen: Mehr Unit-, Widget- und Integration-Tests schreiben.
  • Fehler-Reporting: Integration eines Dienstes wie Sentry oder Firebase Crashlytics.
  • Deployment: Die App für den Google Play Store vorbereiten und veröffentlichen.

Ich hoffe, diese Serie hat dir Spaß gemacht und dir geholfen, Flutter und die App-Entwicklung besser zu verstehen. Nutze das Gelernte als Sprungbrett für deine eigenen Projekte!

Vielen Dank fürs Mitmachen und viel Erfolg bei deinen zukünftigen Flutter-Abenteuern!


Weiterführende Ressourcen & Vertiefung

  1. Open-Meteo Archiv API:
  2. Grünlandtemperatursumme (GTS):
    • Agrarmeteorologische Informationen: Suche nach „Grünlandtemperatursumme Erklärung“ oder „GTS Landwirtschaft“, um mehr über die Bedeutung und Berechnungsmethoden zu erfahren (z.B. von Wetterdiensten oder landwirtschaftlichen Portalen).
  3. Caching-Strategien in Flutter:
    • Einfaches In-Memory Caching: Wie wir es implementiert haben, ist ein guter Start.
    • shared_preferences: https://pub.dev/packages/shared_preferences – Für das Speichern einfacher Schlüssel-Wert-Paare (kleine Datenmengen, die auch nach App-Neustart erhalten bleiben).
    • Lokale Datenbanken (z.B. sqflite): https://pub.dev/packages/sqflite – Für komplexere, strukturierte Daten, die persistent gespeichert werden sollen.
  4. Parallele Ausführung mit Future:

Deine Flutter Wetter-App: Schritt für Schritt – Teil 3

Teil 3: Der erste Meilenstein: Aktuelle Temperatur am aktuellen Ort – Den Code verstehen

Hallo und willkommen zurück zur Serie!

In Teil 2 haben wir unsere Werkzeuge geschärft und die Flutter-Entwicklungsumgebung auf deinem Windows-PC eingerichtet. Wir haben sogar die Standard-Flutter-App zum Laufen gebracht. Super!

Heute tauchen wir endlich in den eigentlichen Code unserer Wetter-App ein. Wir überspringen das manuelle Tippen jedes Zeichens und konzentrieren uns stattdessen darauf, den Code für unseren ersten Meilenstein zu verstehen: Die App soll die aktuelle Temperatur für deinen aktuellen GPS-Standort anzeigen.

Das Ziel für heute:

  • Wir schauen uns den vorbereiteten Code für Teil 3 an (den du aus einem Repository herunterladen kannst).
  • Wir zerlegen die Projektstruktur und verstehen, welche Datei wo hingehört und warum.
  • Wir verfolgen den Datenfluss: Wie kommt die Temperatur vom Internet auf deinen Bildschirm?
  • Wir beleuchten die wichtigsten Konzepte: Architektur, State Management mit Riverpod, Fehlerbehandlung und mehr.

Warum dieser Ansatz?

Eine App zu bauen ist wie ein Haus zu bauen. Man könnte einfach loslegen, aber ein guter Architekt plant zuerst. Wir haben den Code für diesen ersten Schritt bereits nach einem bewährten Plan (einer „sauberen Architektur“) strukturiert. Indem wir diesen fertigen, aber einfachen Code untersuchen, lernst du nicht nur, wie man eine Funktion implementiert, sondern auch, wie man Code organisiert, damit er später leicht erweitert, getestet und gewartet werden kann. Das ist entscheidend, um selbst gute Apps zu schreiben!

Schritt 1: Den Code holen

Der gesamte Code für diesen Teil der Serie ist in einem Git-Repository vorbereitet.

  1. Repository klonen (falls noch nicht geschehen):
    Öffne eine Eingabeaufforderung oder ein Terminal und navigiere zu dem Ordner, in dem du deine Projekte speichern möchtest (z.B. C:\dev\flutter_projekte\). Führe dann folgenden Befehl aus:
    git clone https://github.com/hschewe/flutter_weather_app_blog.git
    Wechsle in das neu erstellte Verzeichnis:
    bash cd flutter_weather_app_blog
  2. Den richtigen Stand auschecken: Für jeden Teil der Serie gibt es einen Git-Tag. Um den Code-Stand für Teil 3 zu bekommen, führe aus:
    git checkout part3-current-temp-gps.
    (Git meldet möglicherweise, dass du dich in einem ‚detached HEAD‘-Zustand befindest. Das ist normal und bedeutet, du schaust dir einen spezifischen Punkt in der Vergangenheit an. Du kannst den den Code untersuchen, ausführen und sogar temporäre Änderungen vornehmen. Wenn du zur normalen Entwicklung zurückkehren willst, kannst du einfach wieder den main-Branch auschecken (git checkout main)).
  3. Projekt in VS Code öffnen: Öffne VS Code und wähle File > Open Folder... und navigiere zum flutter_weather_app_blog-Ordner.
  4. Abhängigkeiten installieren: Öffne ein Terminal in VS Code (Terminal > New Terminal) und führe aus:
    flutter pub get
  5. Code generieren: Da wir Riverpod mit Code-Generierung verwenden, müssen wir diesen Schritt ausführen:
    dart run build_runner build --delete-conflicting-outputs
    Dieser Befehl liest spezielle Anmerkungen (@riverpod) im Code und erstellt automatisch benötigte Hilfsdateien (die auf .g.dart enden).

Jetzt ist der Code bereit zur Untersuchung!

Schritt 2: Der große Überblick – Die Architektur

Bevor wir in einzelne Dateien schauen, betrachten wir den Bauplan. Unsere App folgt einer Schichtenarchitektur, inspiriert von „Clean Architecture“. Stell dir vor, wir bauen Schichten wie bei einer Zwiebel:

+-------------------------------------------------+
| Presentation (UI) Layer                         | <--- Das, was der Nutzer sieht (Widgets, Screens)
|    - Widgets                                    |      Interagiert mit dem Application Layer
|    - Screens                                    |
|    - State Management (Notifier/Provider)       |
+-------------------------------------------------+
      ^                                      | Dependency Rule
      | Calls                                | (Innere Schichten kennen Äußere nicht)
+-------------------------------------------------+
| Application / Domain Layer                      | <--- Die Logik der App
|    - State Notifier (Logik-Orchestrierung)      |      Definiert, WAS die App tut
|    - Repository Interface (Datenvertrag)        |      Kennt nur Entities
|    - Entities (App-Datenstrukturen)             |
+-------------------------------------------------+
      ^                                      |
      | Implements / Calls                   |
+-------------------------------------------------+
| Data Layer                                      | <--- Datenbeschaffung & -speicherung
|    - Repository Implementation                  |      Implementiert den Vertrag
|    - Data Sources (API, GPS, DB)                |      Spricht mit der Außenwelt
|    - Models (API/DB-Datenstrukturen)            |
+-------------------------------------------------+
      ^ Depends on                             ^ Depends on
      |                                        |
+-------------------------------------------------+
| Core Layer                                      | <--- App-übergreifende Helfer
|    - Utils (Logger, Formatter)                  |      Von allen Schichten nutzbar
|    - Error Handling                             |
|    - Networking Client                          |
+-------------------------------------------------+
  • Core: Enthält grundlegende Helferlein, die überall gebraucht werden könnten (wie unser Logger).
  • Data: Kümmert sich darum, woher die Daten kommen (API, GPS) und wie sie technisch abgefragt werden. Kennt die genaue Struktur der externen Daten.
  • Domain/Application: Das Herzstück. Definiert, welche Daten die App braucht (Entities) und welche Operationen möglich sind (Repository Interface), aber nicht, wie sie beschafft werden. Hier sitzt auch die Logik, die auf Nutzeraktionen reagiert (Notifier). Diese Schicht sollte unabhängig von UI-Details oder spezifischen Datenbanken/APIs sein.
  • Presentation (UI): Zeigt die Daten an (Screens, Widgets) und nimmt Nutzereingaben entgegen. Sie spricht nur mit dem Application Layer (über den Notifier), um Daten zu bekommen oder Aktionen auszulösen.

Die goldene Regel: Abhängigkeiten zeigen immer nach innen! Die UI kennt die Application/Domain Layer, aber nicht die Data Layer. Die Domain Layer kennt niemanden außerhalb (außer Core). Das macht das System flexibel und testbar.

Schritt 3: Ein Rundgang durch die Ordner (lib/src/)

Schauen wir uns an, wie diese Architektur in unserer Ordnerstruktur abgebildet ist:

  • lib/main.dart: Der allererste Startpunkt. Initialisiert das Logging, WidgetsFlutterBinding (wichtig für Plugins) und startet die App innerhalb einer ProviderScope (notwendig für Riverpod).
  • lib/app.dart: Enthält das MaterialApp-Widget, das die grundlegende Struktur, das Theme (Aussehen) und die Startseite (WeatherScreen) unserer App definiert.
  • lib/src/core/: Unser Fundament.
    • error/: Enthält exceptions.dart (spezifische technische Fehler wie NetworkException) und failure.dart (abstraktere Fehler wie NetworkFailure, die die Logik verstehen kann). Diese Trennung hilft, Fehler sauber zu behandeln.
    • location/: location_service.dart kapselt die Interaktion mit dem geolocator-Paket. Alle GPS- und Berechtigungs-Anfragen laufen hierüber. Wird über Riverpod bereitgestellt (locationServiceProvider).
    • networking/: http_client.dart stellt eine globale Instanz des http.Client bereit (über httpClientProvider). Das macht es einfach, ihn in Tests durch einen Mock zu ersetzen.
    • utils/: Enthält Helfer wie logger.dart (für strukturierte Logs) und date_formatter.dart (um z.B. die Uhrzeit anzuzeigen).
    • constants/: app_constants.dart sammelt zentrale Konstanten (hier erstmal nur myLocationLabel).
  • lib/src/features/weather/: Alles, was mit der Wetterfunktion zu tun hat.
    • data/: Datenbeschaffung.
      • models/: current_weather_model.dart, forecast_response_model.dart. Diese Dart-Klassen spiegeln exakt die Struktur des JSON wider, das wir von der Open-Meteo API bekommen. Sie enthalten fromJson-Methoden, um JSON in Dart-Objekte umzuwandeln.
      • datasources/: weather_api_service.dart. Spricht über den http.Client mit der Open-Meteo API (getCurrentWeather-Methode). Parst die JSON-Antwort mithilfe der Models und wirft spezifische Exceptions (ApiException, NetworkException, DataParsingException). Wird über Riverpod bereitgestellt (weatherApiServiceProvider).
      • repositories/: weather_repository_impl.dart. Die konkrete Implementierung unseres Datenvertrags. Diese Klasse kennt den WeatherApiService und den LocationService. Sie ruft deren Methoden auf, fängt deren Exceptions ab und wandelt sie in Failures um (z.B. wird NetworkException zu NetworkFailure). Sie wandelt auch die API-Models in die App-internen Entities um. Wird über Riverpod bereitgestellt (weatherRepositoryProvider).
    • domain/: Das Kernstück der App-Logik.
      • entities/: location_info.dart, current_weather_data.dart. Einfache Dart-Klassen, die die Daten repräsentieren, wie sie die App intern benötigt, unabhängig von der API. Nutzen Equatable für einfache Vergleiche.
      • repositories/: weather_repository.dart. Das ist nur ein „Interface“ (abstrakte Klasse). Es definiert, was man mit Wetterdaten tun können muss (z.B. getWeatherForLocation, getCurrentLocationCoordinates), aber nicht wie. Das ist der Vertrag, den die WeatherRepositoryImpl erfüllen muss.
    • application/: Die Orchestrierung.
      • weather_state.dart: Definiert, wie der Zustand des Wetter-Features aussieht: ein enum WeatherStatus (initial, loading, success, failure), die eigentlichen CurrentWeatherData, der selectedLocation und ein optionales Failure-Objekt. Nutzt Equatable und copyWith.
      • weather_notifier.dart: Die Steuerzentrale. Ein StateNotifier, der den WeatherState hält und aktualisiert. Er bekommt das WeatherRepository übergeben (Dependency Injection durch Riverpod). Enthält die Logik für fetchWeatherForCurrentLocation und refreshWeatherData. Er ruft Methoden im Repository auf, behandelt das Either<Failure, Success>-Ergebnis und aktualisiert den state entsprechend.
    • presentation/: Die Benutzeroberfläche.
      • providers/: weather_providers.dart. Definiert den weatherNotifierProvider, der den WeatherNotifier erstellt und der UI zur Verfügung stellt.
      • widgets/: Kleine, wiederverwendbare UI-Teile. location_header.dart zeigt den Ortsnamen, current_temperature_display.dart zeigt die Temperatur und Zeit. Sie bekommen ihre Daten von außen übergeben.
      • screens/: weather_screen.dart. Der Hauptbildschirm. Ein ConsumerStatefulWidget, das über ref.watch(weatherNotifierProvider) den aktuellen WeatherState bekommt. Basierend auf dem status im State, zeigt es entweder einen Ladeindikator, die Wetter-Widgets oder eine Fehlermeldung (_buildErrorWidget). Es nutzt ref.read(weatherNotifierProvider.notifier) um Aktionen im Notifier auszulösen (initiales Laden, Refresh). Der RefreshIndicator ermöglicht Pull-to-Refresh. Der AnimatedSwitcher sorgt für weiche Übergänge.

Schritt 4: Den Datenfluss verstehen

Wie hängt das alles zusammen, wenn die App startet?

  1. Start (main.dart -> app.dart -> WeatherScreen): Die App wird initialisiert, ProviderScope wird erstellt. WeatherScreen wird angezeigt.
  2. Initial Load (WeatherScreen.initState): Der Screen merkt, dass er neu ist (initialState.status == WeatherStatus.initial) und triggert über ref.read(weatherNotifierProvider.notifier).fetchWeatherForCurrentLocation() den Ladevorgang im Notifier.
  3. Loading State (WeatherNotifier): Der Notifier setzt sofort seinen state auf status: WeatherStatus.loading.
  4. UI Reaction (WeatherScreen): Da der Screen via ref.watch auf den State hört, wird er neu gebaut und zeigt jetzt (im _buildContent) einen Ladeindikator an.
  5. Get Coordinates (WeatherNotifier -> WeatherRepository -> LocationService):
    • Notifier ruft _weatherRepository.getCurrentLocationCoordinates() auf.
    • Das Repo (WeatherRepositoryImpl) ruft _locationService.getCurrentPosition() auf.
    • Der LocationService interagiert mit dem geolocator, fragt ggf. nach Berechtigungen und holt die Position.
    • Wenn erfolgreich, gibt der Service die Position zurück. Wenn ein Fehler auftritt (z.B. Berechtigung verweigert), wirft er eine LocationException.
    • Das Repo fängt die Exception, wandelt sie ggf. in eine Failure (PermissionFailure, LocationFailure) um und gibt Left(failure) zurück. Bei Erfolg erstellt es LocationInfo und gibt Right(locationInfo) zurück.
  6. Handle Coordinates Result (WeatherNotifier):
    • Der Notifier erhält das Either. Bei Left(failure) setzt er den state auf status: WeatherStatus.failure mit dem failure-Objekt -> Die UI zeigt die Fehlermeldung.
    • Bei Right(locationInfo) geht es weiter. Der Notifier versucht noch, den Namen via _weatherRepository.getLocationDisplayName zu holen (was in Teil 3 noch nicht viel tut) und ruft dann _fetchWeatherDataAndUpdateState(finalLocationInfo) auf.
  7. Get Weather Data (WeatherNotifier -> WeatherRepository -> WeatherApiService):
    • Notifier ruft _weatherRepository.getWeatherForLocation(locationInfo) auf.
    • Das Repo (WeatherRepositoryImpl) ruft _apiService.getCurrentWeather(...) auf.
    • Der WeatherApiService baut die URL, macht den http.get-Aufruf, parst das JSON in ForecastResponseModel, extrahiert CurrentWeatherModel. Bei Fehlern (Netzwerk, API-Status, Parsing) wirft er NetworkException, ApiException, DataParsingException.
    • Das Repo fängt diese Exceptions, wandelt sie in Failures (NetworkFailure, ServerFailure) um und gibt Left(failure) zurück. Bei Erfolg wandelt es CurrentWeatherModel in CurrentWeatherData (unser App-Entity) um und gibt Right(weatherData) zurück.
  8. Handle Weather Result (WeatherNotifier):
    • Der Notifier erhält das Either. Bei Left(failure) setzt er den state auf status: WeatherStatus.failure mit dem failure-Objekt -> Die UI zeigt die Fehlermeldung.
    • Bei Right(weatherData) setzt er den state auf status: WeatherStatus.success, speichert weatherData und locationInfo im State und löscht den Fehler (clearError: true).
  9. UI Reaction (WeatherScreen): Der Screen hört wieder auf die State-Änderung (ref.watch). Er wird neu gebaut, _buildContent erkennt WeatherStatus.success und zeigt jetzt LocationHeader und CurrentTemperatureDisplay mit den Daten aus dem state an.

Schritt 5: Schlüsselkonzepte im Code

  • Riverpod für State Management & Dependency Injection:
    • ProviderScope (in main.dart): Macht Provider global verfügbar.
    • @riverpod / ...Provider (z.B. in location_service.dart, weather_repository_impl.dart): Definiert, wie eine Instanz eines Service oder Repositories erstellt wird. Riverpod kümmert sich darum, dass nur eine Instanz erstellt und wiederverwendet wird. Das ist Dependency Injection: Komponenten bekommen ihre Abhängigkeiten (wie den http.Client oder den LocationService) „injiziert“, statt sie selbst zu erstellen.
    • StateNotifierProvider (weather_providers.dart): Ein spezieller Provider für unseren WeatherNotifier, der dessen Zustand (WeatherState) verwaltet.
    • ConsumerWidget / ConsumerStatefulWidget (WeatherScreen): Widgets, die auf Provider „hören“ können.
    • ref.watch() (im build von WeatherScreen): Liest den Wert eines Providers und baut das Widget neu, wenn sich der Wert (hier der WeatherState) ändert.
    • ref.read() (im initState oder in Callbacks wie onPressed von WeatherScreen): Liest den Wert eines Providers einmalig, ohne auf Änderungen zu hören. Wird verwendet, um Methoden im Notifier aufzurufen.
  • Fehlerbehandlung (Either, Failure, Exception):
    • Services (LocationService, WeatherApiService) werfen spezifische Exceptions bei technischen Problemen.
    • Das Repository (WeatherRepositoryImpl) fängt diese Exceptions und wandelt sie in allgemeinere Failures um. Es gibt das Ergebnis als Either<Failure, Success> zurück – ein klarer Weg, um Erfolg oder Misserfolg zu signalisieren, ohne Exceptions durch die ganze App zu werfen.
    • Der Notifier (WeatherNotifier) behandelt das Either-Ergebnis und aktualisiert den WeatherState entsprechend (status: WeatherStatus.failure oder success).
    • Die UI (WeatherScreen) reagiert auf den status und das error-Feld im State und zeigt die passende Ansicht.
  • Asynchronität (Future, async, await): Netzwerk- und GPS-Anfragen dauern eine Weile. Future repräsentiert einen Wert, der irgendwann verfügbar sein wird. async markiert eine Funktion, die await verwenden kann. await pausiert die Ausführung der Funktion, bis der Future abgeschlossen ist, ohne die gesamte App zu blockieren. Wir sehen das intensiv im Notifier, Repository und den Services.
  • Immutability & Equatable: Der WeatherState wird nie direkt geändert. Stattdessen wird mit copyWith eine neue Instanz mit den geänderten Werten erstellt. Das macht den Zustandsfluss vorhersagbar. Equatable hilft Riverpod (und uns beim Testen), effizient zu erkennen, ob sich der Zustand wirklich geändert hat, indem es Objekte anhand ihrer Eigenschaften vergleicht, nicht nur anhand ihrer Speicheradresse.

Schritt 6: Ausführen und Experimentieren!

Jetzt, wo du eine Vorstellung davon hast, wie der Code aufgebaut ist und funktioniert:

  1. Starte die App: Wähle dein Gerät in VS Code und drücke F5.
  2. Beobachte: Verfolge die Log-Ausgaben im „DEBUG CONSOLE“-Fenster von VS Code. Du solltest die Meldungen von AppLogger aus den verschiedenen Schichten sehen.
  3. Experimentiere:
    • Ändere Texte in den Widgets.
    • Setze Haltepunkte (Breakpoints) in VS Code (klicke links neben die Zeilennummer) in verschiedenen Methoden (z.B. im Notifier, im Repo, im Service) und starte die App im Debug-Modus (F5). Steppe durch den Code (F10, F11), um den Fluss live zu sehen.
    • Simuliere Fehler: Wirf testweise eine Exception im WeatherApiService oder gib Left(NetworkFailure()) im Repository zurück, um zu sehen, wie die Fehlerbehandlung in der UI greift.

Zusammenfassung und Nächste Schritte

Das war ein tiefer Einblick in den Code unseres ersten Meilensteins! Du hast gesehen, wie wir mit einer klaren Architektur und Werkzeugen wie Riverpod eine skalierbare und testbare Grundlage geschaffen haben, auch für eine zunächst einfache Funktion. Du verstehst jetzt (hoffentlich!) besser:

  • Die Aufteilung in Schichten (Presentation, Domain/Application, Data, Core).
  • Die Verantwortlichkeiten der einzelnen Komponenten (Widgets, Notifier, Repositories, Services).
  • Den Daten- und Kontrollfluss durch die App.
  • Die Grundprinzipien von State Management, Fehlerbehandlung und Asynchronität in Flutter.

Im nächsten Teil (Teil 4) bauen wir darauf auf und machen die App interaktiver: Wir fügen die Adresssuche hinzu!

Bleib dran und viel Spaß beim Erkunden des Codes!


Weiterführende Ressourcen & Vertiefung (für Teil 3)

Dieser Teil hat viele grundlegende Konzepte der Flutter-Entwicklung eingeführt. Hier sind Links zum Vertiefen:

  1. Projektstruktur & Architektur:
    • Flutter App architecture samples (GitHub): https://github.com/flutter/samples/tree/main/experimental/context_menus (Beispielhaft, es gibt viele Ansätze) – Oft komplex, aber gibt Ideen. Unsere Struktur ist eine vereinfachte Form, die oft als „Feature-First“ mit Schichtentrennung bezeichnet wird.
    • Clean Architecture in Flutter (Artikel/Videos): Suche nach „Clean Architecture Flutter“ für verschiedene Interpretationen und Erklärungen (z.B. von Reso Coder, Vandad Nahavandipoor).
  2. Flutter Pakete (Dependencies):
  3. State Management (Riverpod):
  4. Dart Grundlagen:
  5. Android Spezifika:

Deine Flutter Wetter-App: Schritt für Schritt – Teil 2

Teil 2: Das Fundament legen – Deine Flutter-Entwicklungsumgebung unter Windows einrichten

Hallo zurück zu unserer Flutter-Wetter-App-Serie!

In Teil 1 haben wir uns angesehen, was wir bauen wollen – eine Wetter-App mit aktuellen Daten, Verlauf, Prognose und sogar der Grünlandtemperatursumme – und warum eine Wetter-App ein großartiges Lernprojekt ist. Bevor wir jedoch die erste Zeile Code für unsere App schreiben können, brauchen wir das richtige Werkzeug und eine eingerichtete Werkstatt.

Genau das ist das Ziel dieses zweiten Teils: Wir legen heute das Fundament und richten deine Entwicklungsumgebung auf deinem Windows-Rechner ein. Keine Sorge, das klingt vielleicht erstmal nach viel, aber es ist ein einmaliger Prozess. Wir gehen alles Schritt für Schritt durch!

Was wir heute tun:

  1. Flutter SDK installieren: Das Herzstück, das alle nötigen Werkzeuge und Bibliotheken für Flutter enthält.
  2. Android Studio installieren: Auch wenn wir hauptsächlich mit VS Code arbeiten, brauchen wir Android Studio für wichtige Android-spezifische Werkzeuge (SDK, Emulator).
  3. flutter doctor ausführen: Unser Diagnose-Tool, das prüft, ob alles korrekt eingerichtet ist.
  4. Ein Testgerät einrichten: Entweder einen Emulator (ein virtuelles Handy) oder dein echtes Android-Smartphone vorbereiten.
  5. Visual Studio Code (VS Code) konfigurieren: Unseren bevorzugten Code-Editor mit den nötigen Flutter-Erweiterungen ausstatten.
  6. Das erste Flutter-Projekt erstellen und starten: Sicherstellen, dass die Standard-App läuft und unsere Umgebung bereit ist.

Los geht’s!

Schritt 1: Flutter SDK installieren

Das Flutter SDK (Software Development Kit) ist eine Sammlung von Werkzeugen, die es uns ermöglichen, Flutter-Anwendungen zu entwickeln und zu kompilieren.

  1. Download: Gehe zur offiziellen Flutter-Installationsseite für Windows: https://docs.flutter.dev/get-started/install/windows
    • Lade die neueste stabile Version des Flutter SDK als ZIP-Datei herunter (suche nach dem blauen Button „Download the latest stable release of the Flutter SDK“).
  2. Entpacken: Erstelle einen Ordner direkt auf deinem Laufwerk C: (oder einem anderen Laufwerk, wenn du möchtest), zum Beispiel C:\flutter\. Wichtig: Entpacke das Flutter SDK nicht in Ordner wie C:\Program Files\ oder C:\Program Files (x86)\, da diese oft spezielle Berechtigungen erfordern, die zu Problemen führen können.
    • Entpacke den Inhalt der heruntergeladenen ZIP-Datei in den neu erstellten C:\flutter\ Ordner. Du solltest jetzt einen Pfad wie C:\flutter\bin haben.
  3. PATH-Umgebungsvariable aktualisieren: Damit dein Computer weiß, wo er die Flutter-Befehle finden kann, müssen wir den Pfad zum bin-Ordner von Flutter zur sogenannten PATH-Umgebungsvariable hinzufügen.
    • Gib „Umgebungsvariablen“ in die Windows-Suche ein und wähle „Systemumgebungsvariablen bearbeiten“.
    • Klicke im neuen Fenster unten auf den Button „Umgebungsvariablen…“.
    • Suche im oberen Bereich („Benutzervariablen für [Dein Benutzername]“) die Variable Path. Wähle sie aus und klicke auf „Bearbeiten…“. (Wenn sie nicht existiert, klicke auf „Neu…“.)
    • Klicke auf „Neu“ und füge den vollständigen Pfad zu deinem Flutter bin-Ordner hinzu: C:\flutter\bin (passe dies an, falls du Flutter woanders entpackt hast).
    • Bestätige alle offenen Fenster mit „OK“.
    • Wichtig: Damit die Änderung wirksam wird, musst du alle bereits geöffneten Kommandozeilenfenster (Eingabeaufforderung oder PowerShell) schließen und neu öffnen. Manchmal ist sogar ein Neustart des PCs nötig.
  4. Überprüfung: Öffne eine neue Eingabeaufforderung (cmd) oder PowerShell und gib den Befehl ein:
    bash flutter --version
    Wenn alles geklappt hat, sollte Flutter dir nun seine Version und weitere Informationen anzeigen. Herzlichen Glückwunsch, Flutter ist installiert!

Schritt 2: Android Studio installieren (für Android SDK & Co.)

Auch wenn wir VS Code zum Schreiben unseres Codes verwenden, ist Android Studio unerlässlich, da es das Android SDK, die Build-Tools und den Emulator-Manager mitbringt.

  1. Download: Lade Android Studio von der offiziellen Seite herunter: https://developer.android.com/studio
  2. Installation: Führe die heruntergeladene .exe-Datei aus und folge dem Installationsassistenten. Wähle die Standardeinstellungen („Standard“ oder „Recommended“). Android Studio wird das neueste Android SDK, die SDK Platform-Tools und die SDK Build-Tools herunterladen und installieren.
    • Merke dir den Installationsort des Android SDKs. Normalerweise ist das so etwas wie C:\Users\DEIN_BENUTZERNAME\AppData\Local\Android\Sdk. Du findest ihn auch später in Android Studio unter File > Settings > Languages & Frameworks > Android SDK.
  3. Android Studio starten: Starte Android Studio nach der Installation. Es wird eventuell noch einige Komponenten herunterladen.
  4. (Optional, aber empfohlen) Flutter und Dart Plugins: Auch wenn wir VS Code nutzen, installieren wir die Flutter- und Dart-Plugins in Android Studio. Das hilft flutter doctor bei der Erkennung und kann nützlich sein, falls du doch mal eine Funktion von Android Studio brauchst.
    • Gehe in Android Studio zu File > Settings > Plugins.
    • Suche im „Marketplace“-Tab nach „Flutter“ und klicke auf „Install“. Akzeptiere die Installation des Dart-Plugins, wenn du dazu aufgefordert wirst.
    • Starte Android Studio neu, wenn du dazu aufgefordert wirst.
  5. Android SDK Command-line Tools: Stelle sicher, dass diese installiert sind.
    • Gehe in Android Studio zu File > Settings > Languages & Frameworks > Android SDK.
    • Wähle den Tab „SDK Tools“.
    • Setze einen Haken bei „Android SDK Command-line Tools (latest)“.
    • Klicke auf „Apply“ oder „OK“, um sie zu installieren.
  6. Android-Lizenzen akzeptieren: Flutter muss sicherstellen, dass du die Lizenzen für das Android SDK akzeptiert hast. Öffne eine neue Eingabeaufforderung oder PowerShell und führe aus:
    bash flutter doctor --android-licenses
    Lies die Lizenzbedingungen durch und gib bei jeder Abfrage y (für yes) ein, um sie zu akzeptieren.

Schritt 3: flutter doctor – Der Gesundheitscheck

Jetzt ist es Zeit für einen Check-up! flutter doctor ist ein Befehl, der deine Umgebung überprüft und dir sagt, ob alles für die Flutter-Entwicklung bereit ist oder ob noch etwas fehlt.

Öffne eine neue Eingabeaufforderung oder PowerShell und führe aus:

flutter doctor

Du wirst eine Ausgabe ähnlich dieser sehen (kann bei dir leicht abweichen):

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.x.x, on Microsoft Windows [Version ...], locale de-DE)
[✓] Android toolchain - develop for Android devices (Android SDK version 3x.x.x)
[✓] Chrome (visualize Flutter web apps with Chrome)
[!] Visual Studio - develop for Windows (Visual Studio not installed)  <-- Ignorieren, wenn du nur für Android entwickelst
[✓] Android Studio (version 202x.x.x)
[✓] VS Code (version 1.x.x)
[✓] Connected device (1 available)                                  <-- Oder 'No devices available'
[✓] Network resources

* No issues found!
  • Was bedeutet das?
    • [✓] (Haken): Alles in Ordnung für diese Komponente!
    • [!] (Ausrufezeichen): Es gibt ein Problem oder eine Empfehlung. Lies die Meldung genau durch, flutter doctor gibt oft Hinweise zur Lösung. (Das Visual Studio für Windows-Entwicklung kannst du ignorieren, wenn du nur für Android entwickelst).
    • [✗] (Kreuz): Etwas Wichtiges fehlt oder ist falsch konfiguriert.
    • [?] (Fragezeichen): Etwas konnte nicht überprüft werden.
  • Ziel: Wir wollen Haken bei Flutter, Android toolchain, Android Studio (oder zumindest, dass es erkannt wird) und später bei VS Code und Connected device.
  • Keine Panik: Wenn nicht sofort alles grün ist, ist das normal! Lies die Meldungen von flutter doctor und folge den Anweisungen. Oft fehlt nur ein kleiner Schritt oder ein Neustart.

Schritt 4: Ein Testgerät einrichten

Um deine App zu sehen und zu testen, brauchst du ein Android-Gerät. Du hast zwei Möglichkeiten:

Option A: Android Emulator (Virtuelles Gerät)

Ein Emulator simuliert ein Android-Gerät auf deinem Computer.

  1. AVD Manager öffnen: Klicke auf dem Willkommensbildschirm auf More Actions -> Virtual Device Manager (oder wenn ein Projekt offen ist: Tools -> Device Manager).
  2. Gerät erstellen: Klicke auf „Create device“.
    • Wähle eine Hardware aus (z.B. „Pixel 6“ oder eine ähnliche, aktuelle Geräteklasse). Klicke „Next“.
    • Wähle ein System-Image aus (eine Android-Version). Lade eines herunter, falls noch keines vorhanden ist (empfohlen: eine relativ aktuelle API-Version, z.B. API 33 oder 34). Klicke „Next“.
    • Gib dem virtuellen Gerät (AVD) einen Namen und klicke auf „Finish“.
  3. Emulator starten: Wähle dein neu erstelltes Gerät im Device Manager aus und klicke auf das Play-Symbol (▶️) in der „Actions“-Spalte, um es zu starten. Es kann einen Moment dauern, bis der Emulator hochgefahren ist.
    • Performance-Hinweis: Emulatoren können auf manchen Rechnern langsam sein. Stelle sicher, dass die Hardware-Virtualisierung (Intel HAXM oder AMD Hypervisor / Windows Hypervisor Platform) in deinem BIOS/UEFI aktiviert ist und in Android Studio konfiguriert wurde (passiert oft automatisch).

Option B: Physisches Android-Gerät (Dein Smartphone)

Du kannst auch dein eigenes Android-Handy zum Testen verwenden.

  1. Entwickleroptionen aktivieren: Gehe auf deinem Handy zu Einstellungen > Über das Telefon. Tippe dort mehrmals schnell hintereinander auf die „Build-Nummer“, bis eine Meldung erscheint wie „Du bist jetzt Entwickler!“.
  2. USB-Debugging aktivieren: Gehe zurück zu den Einstellungen. Suche nach dem neuen Menüpunkt Entwickleroptionen (manchmal unter System > Erweitert). Aktiviere dort die Option USB-Debugging. Bestätige die Warnmeldung.
  3. USB-Treiber (falls nötig): Verbinde dein Handy per USB-Kabel mit dem Computer. Windows versucht normalerweise, die richtigen Treiber automatisch zu installieren. Falls dein Gerät nicht erkannt wird, suche auf der Website des Handy-Herstellers nach spezifischen „OEM USB Drivers“ für dein Modell und installiere sie.
  4. Verbindung autorisieren: Wenn du dein Handy zum ersten Mal mit aktiviertem USB-Debugging verbindest, erscheint auf dem Handy eine Meldung „USB-Debugging zulassen?“. Setze einen Haken bei „Von diesem Computer immer zulassen“ und tippe auf „OK“ oder „Zulassen“.

Überprüfung: Egal ob Emulator oder echtes Gerät, öffne eine neue Eingabeaufforderung und führe aus:

flutter devices

Dein verbundenes Gerät oder der laufende Emulator sollte nun in der Liste erscheinen! flutter doctor sollte jetzt auch einen Haken bei Connected device zeigen.

Schritt 5: Visual Studio Code (VS Code) einrichten

VS Code ist unser bevorzugter Editor zum Schreiben des Flutter-Codes.

  1. Download & Installation: Lade VS Code herunter und installiere es: https://code.visualstudio.com/ . Die Installation ist unkompliziert.
  2. Flutter Extension installieren:
    • Starte VS Code.
    • Klicke auf das Extensions-Symbol in der linken Seitenleiste (sieht aus wie vier Quadrate).
    • Suche nach „Flutter“.
    • Wähle die offizielle Extension von „Dart Code“ aus und klicke auf „Install“. Diese Extension installiert automatisch auch die notwendige „Dart“-Extension.
    • Starte VS Code neu, wenn du dazu aufgefordert wirst.

Schritt 6: Das erste Flutter-Projekt erstellen und starten

Endlich! Zeit, unser erstes (Standard-)Flutter-Projekt zu erstellen und zu sehen, ob alles funktioniert.

  1. Projekt erstellen:
    • Öffne VS Code.
    • Öffne die Command Palette mit Strg+Shift+P (oder Ctrl+Shift+P).
    • Tippe „Flutter: New Project“ und wähle die Option aus.
    • Wähle „Application“.
    • Wähle einen Ordner auf deinem Computer, wo das Projekt gespeichert werden soll (z.B. C:\dev\flutter_projekte\).
    • Gib einen Namen für dein Projekt ein. Wichtig: Der Name muss klein geschrieben sein und darf nur Buchstaben, Zahlen und Unterstriche enthalten (z.B. flutter_weather_app_blog). Drücke Enter.
    • VS Code erstellt nun die Projektstruktur und lädt eventuell noch benötigte Pakete herunter. Das kann einen Moment dauern.
  2. Gerät auswählen: Stelle sicher, dass dein Emulator läuft oder dein Handy verbunden und erkannt ist. In der unteren rechten Ecke der VS Code Statusleiste solltest du nun dein Gerät auswählen können (klicke auf den Gerätenamen oder „No Device“).
  3. App starten:
    • Öffne die Datei lib/main.dart. Das ist der Einstiegspunkt der App.
    • Drücke F5 oder gehe im Menü auf Run > Start Debugging.
    • Flutter wird nun die App kompilieren und auf deinem ausgewählten Gerät installieren und starten. Der erste Start kann etwas länger dauern.
  4. Erfolg! Du solltest nun die Flutter-Standard-Demo-App sehen (die mit dem Zähler und dem blauen Button). Wenn du auf den Button tippst, erhöht sich der Zähler.

Wenn etwas nicht klappt (Troubleshooting):

  • flutter Befehl nicht gefunden: Überprüfe nochmal genau die PATH-Variable (Schritt 1.3). Hast du den richtigen Pfad (C:\flutter\bin) hinzugefügt? Hast du die Eingabeaufforderung/VS Code neu gestartet? Manchmal hilft ein PC-Neustart.
  • flutter doctor zeigt Fehler bei Android toolchain: Stelle sicher, dass Android Studio korrekt installiert ist, die Command-line Tools vorhanden sind (Schritt 2.5) und du die Lizenzen akzeptiert hast (Schritt 2.6). Manchmal muss man Flutter explizit sagen, wo das SDK liegt: flutter config --android-sdk C:\Users\DEIN_BENUTZERNAME\AppData\Local\Android\Sdk (Pfad anpassen).
  • Emulator startet nicht oder ist sehr langsam: Überprüfe die Virtualisierungs-Einstellungen im BIOS/UEFI deines PCs und stelle sicher, dass HAXM/Hypervisor installiert und aktiviert ist (Android Studio hilft dabei oft). Gib dem Emulator ggf. mehr RAM in den AVD-Einstellungen (aber nicht zu viel!).
  • Echtes Gerät wird nicht erkannt: USB-Debugging aktiviert? Verbindung autorisiert? Richtige USB-Treiber installiert? Probiere ein anderes USB-Kabel oder einen anderen USB-Port.
  • Weitere Hilfe: Die offizielle Flutter-Dokumentation (https://docs.flutter.dev/get-started/install/windows) ist sehr detailliert und eine großartige Ressource bei Problemen.

Geschafft! Was kommt als Nächstes?

Puh, das war der aufwendigste, aber notwendige Teil! Du hast jetzt eine voll funktionsfähige Flutter-Entwicklungsumgebung auf deinem Windows-Rechner. Dein Werkzeugkasten ist bereit!

Herzlichen Glückwunsch zu diesem wichtigen Meilenstein! 🎉

Im nächsten Teil (Teil 3) wird es richtig spannend: Wir werfen den Demo-Code raus und beginnen mit der Entwicklung unserer Wetter-App. Wir werden:

  • Die Projektstruktur und Architektur anlegen (Services, Repository, State Management mit Riverpod).
  • Den aktuellen GPS-Standort des Geräts abfragen.
  • Unsere erste API-Anfrage an Open-Meteo senden, um die aktuelle Temperatur zu bekommen.
  • Die Temperatur auf dem Bildschirm anzeigen.
  • Erklären, warum wir von Anfang an auf eine solide Architektur setzen.

Bleib dran, es geht jetzt richtig los mit dem Code!


Weiterführende Ressourcen & Vertiefung (für Teil 2)

Die Einrichtung der Entwicklungsumgebung ist ein entscheidender Schritt. Hier sind Links zu den offiziellen Anleitungen und wichtigen Werkzeugen:

  1. Flutter SDK Installation (Windows):
  2. Android Studio & Android SDK:
  3. flutter doctor:
  4. Android-Geräte für Tests einrichten:
  5. Visual Studio Code & Flutter Extension:

© 2025 Allround-Blog

Theme von Anders NorénHoch ↑