Skip to content

Kapitel 16: Häufige Fehler

16.1 Häufiger Fehler 1: Umgebungsaufbau fehlgeschlagen

Problem: flutter doctor zeigt Fehler an

Fehlermeldung:

[!] Android toolchain - develop for Android devices
    X Unable to locate Android SDK

Ursache:

  • Android SDK nicht installiert oder Pfad nicht korrekt konfiguriert

Lösung:

  1. Android Studio installieren
  2. ANDROID_HOME Umgebungsvariable setzen:
    bash
    # Windows (PowerShell)
    $env:ANDROID_HOME = "C:\Users\IHR_NAME\AppData\Local\Android\Sdk"
    [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', 'C:\Users\IHR_NAME\AppData\Local\Android\Sdk', 'User')
    
    # Mac/Linux
    export ANDROID_HOME="$HOME/Android/Sdk"
    echo 'export ANDROID_HOME="$HOME/Android/Sdk"' >> ~/.bashrc
  3. flutter doctor --android-licenses ausführen

Problem: Emulator startet nicht

Ursache:

  • HAXM nicht installiert (Intel-CPUs)
  • Zu wenig Speicher

Lösung:

  1. Android Studio → SDK Manager → SDK Tools → Intel x86 Emulator Accelerator installieren
  2. AVD Manager → Emulator bearbeiten → RAM auf 1024 MB reduzieren

16.2 Häufiger Fehler 2: Layout-Überlauf (Renderflex overflowed)

Problem: Widget passt nicht in verfügbaren Platz

Fehlermeldung:

A RenderFlex overflowed by 100 pixels on the right.

Ursache:

  • Widget ist breiter als der Bildschirm
  • Row oder Column hat zu viele Kinder

Lösungen:

1. Expanded verwenden:

dart
Row(
  children: <Widget>[
    Expanded(  // Nimmt verfügbaren Platz ein
      child: Text('Sehr langer Text der überläuft...'),
    ),
    Icon(Icons.more_vert),
  ],
)

2. SingleChildScrollView verwenden:

dart
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(...),
)

3. Flexible verwenden:

dart
Row(
  children: <Widget>[
    Flexible(
      child: Text('Langer Text...'),
    ),
    Icon(Icons.more_vert),
  ],
)

16.3 Häufiger Fehler 3: Zustandsverwaltungsfehler

Problem: setState() wird vergessen

Fehlerhaft:

dart
void _erhoehen() {
  _zaehler++;  // UI wird NICHT aktualisiert!
}

Richtig:

dart
void _erhoehen() {
  setState(() {
    _zaehler++;  // UI wird aktualisiert!
  });
}

Problem: Zustand kann nicht zwischen Widgets geteilt werden

Fehler: Versuch, Zustand direkt zwischen nicht-verwandten Widgets zu teilen.

Lösung: Provider oder andere Zustandsverwaltungs-Lösung verwenden:

dart
// Zustands-Klasse definieren
class CounterProvider extends ChangeNotifier {
  int _zaehler = 0;
  
  int get zaehler => _zaehler;
  
  void erhoehen() {
    _zaehler++;
    notifyListeners();  // WICHTIG: Benachrichtigt alle Zuhörer!
  }
}

// In main.dart bereitstellen
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CounterProvider(),
      child: const MyApp(),
    ),
  );
}

// In UI verwenden
class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final provider = Provider.of<CounterProvider>(context);
    
    return ElevatedButton(
      onPressed: () {
        provider.erhoehen();
      },
      child: Text('${provider.zaehler}'),
    );
  }
}

Problem: notifyListeners() vergessen (bei Provider)

Fehlerhaft:

dart
void erhoehen() {
  _zaehler++;
  // notifyListeners() vergessen! UI wird nicht aktualisiert.
}

Richtig:

dart
void erhoehen() {
  _zaehler++;
  notifyListeners();  // UI wird aktualisiert!
}

16.4 Häufiger Fehler 4: Netzwerkrequest fehlgeschlagen

Problem: Internet-Berechtigung fehlt (Android)

Fehler: App kann keine Netzwerkanfragen senden.

Lösung: android/app/src/main/AndroidManifest.xml bearbeiten:

xml
<manifest xmlns:android="...">
    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- Weitere Konfiguration -->
</manifest>

Problem: Request-Adresse falsch

Fehlerhaft:

dart
final response = await dio.get('htt://example.com');  // FALSCHE URL

Richtig:

dart
final response = await dio.get('https://example.com');  // RICHTIG

Problem: Parameterformat falsch

Fehlerhaft:

dart
// FALSCH: Parameter direkt an URL anhängen
dio.get('https://example.com/api?limit=5');

Richtig:

dart
// RICHTIG: queryParameters verwenden
dio.get('https://example.com/api', queryParameters: {'limit': 5});

Problem: await vergessen

Fehlerhaft:

dart
void ladeDaten() {
  final response = dio.get('https://example.com');  // Future nicht awaited!
  print(response.data);  // Fehler: response ist kein Response-Objekt
}

Richtig:

dart
Future<void> ladeDaten() async {
  final response = await dio.get('https://example.com');  // await verwenden!
  print(response.data);
}

16.5 Häufiger Fehler 5: JSON-Parsing fehlgeschlagen

Problem: JSON-Struktur stimmt nicht mit Dart-Klasse überein

Fehler:

dart
// FALSCH: JSON-Struktur stimmt nicht mit Dart-Klasse überein
final post = Post.fromJson(response.data);  // Fehler!

Lösung:

  1. Überprüfen Sie die JSON-Struktur der API-Antwort
  2. Stellen Sie sicher, dass Ihre Dart-Klasse mit dem JSON übereinstimmt
  3. Verwenden Sie QuickType oder json_serializable

Beispiel(JSON):

json
{
  "id": 1,
  "title": "BeispielTitel",
  "body": "BeispielInhalt"
}

Richtige Dart-Klasse:

dart
class Post {
  final int id;
  final String title;
  final String body;
  
  Post({required this.id, required this.title, required this.body});
  
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

16.6 Häufiger Fehler 6: Packaging fehlgeschlagen

Problem: Signierungs-Konfiguration falsch

Fehler: key.properties nicht gefunden oder Pfad falsch.

Lösung:

  • Stellen Sie sicher, dass android/key.properties existiert
  • Pfad in build.gradle korrekt

Beispiel (android/key.properties):

properties
storePassword=ihr_passwort
keyPassword=ihr_passwort
keyAlias=key
storeFile=d:/key.jks  # Pfad zum key.jks

Beispiel (android/app/build.gradle):

gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    ...
    
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
    }
    
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Problem: Berechtigungen vergessen

Fehler: App stürzt ab, weil Berechtigung fehlt.

Lösung:

  • AndroidManifest.xml für Android bearbeiten
  • Info.plist für iOS bearbeiten

Beispiel (Android):

xml
<manifest xmlns:android="...">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <!-- Weitere Berechtigungen -->
</manifest>

Beispiel (iOS):

xml
<key>NSCameraUsageDescription</key>
<string>App benötigt Kamerazugriff</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App benötigt Zugriff auf Fotos</string>

Problem: Icon-Konfiguration falsch

Fehler: App-Icon wird nicht angezeigt.

Lösung:

  1. flutter_launcher_icons Plugin verwenden
  2. Manuell in android/app/src/main/res/ und ios/Runner/Assets.xcassets/ prüfen

Beispiel (pubspec.yaml):

yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_launcher_icons: ^0.13.0

flutter_icons:
  android: "launcher_icon"
  ios: true
  image_path: "assets/icon/icon.png"
bash
flutter pub get
flutter pub run flutter_launcher_icons

16.7 Debugging-Tipps

1. print() - Einfache Ausgabe

dart
print('Aktueller Wert: $wert');

2. debugPrint() - Besser für lange Ausgaben

dart
import 'package:flutter/foundation.dart';
debugPrint('Lange Nachricht...');

3. assert() - Nur im Debug-Modus

dart
assert(wert != null, 'Wert darf nicht null sein!');

4. Flutter DevTools (Performance, UI, Speicher)

Befehl:

bash
flutter devtools

5. VS Code Debugging

  1. Haltepunkt setzen (roter Punkt links neben Zeilennummer)
  2. F5 drücken oder "Run → Start Debugging"
  3. Debug-Konsole verwenden, um Variablen zu inspizieren

6. Android Studio Debugging

  1. Haltepunkt setzen
  2. "Debug" Button drücken (grüner Käfer)
  3. Debugger-Tab verwenden

Zusammenfassung

In diesem Kapitel haben Sie:

  • ✅ Häufige Fehler bei Umgebungsaufbau behoben gelernt
  • ✅ Layout-Überlauf-Fehler behoben gelernt
  • ✅ Zustandsverwaltungsfehler behoben gelernt
  • ✅ Netzwerkrequest-Fehler behoben gelernt
  • ✅ JSON-Parsing-Fehler behoben gelernt
  • ✅ Packaging-Fehler behoben gelernt
  • ✅ Debugging-Tipps gelernt

Nächstes Kapitel: Wir werden fortgeschrittene Tipps lernen (Code-Optimierung, Performance).


Übungsaufgaben:

  1. Beheben Sie einen Layout-Überlauf-Fehler in einer bestehenden App
  2. Implementieren Sie Zustandsverwaltung mit Provider und beheben Sie notifyListeners()-Vergessen-Fehler
  3. Beheben Sie einen Netzwerkrequest-Fehler (falsche URL, vergessenes await)
  4. Beheben Sie einen JSON-Parsing-Fehler (Struktur stimmt nicht überein)
  5. Beheben Sie einen Packaging-Fehler (Signierungs-Konfiguration, Berechtigungen)

Häufige Fehler:

  • setState() vergessen → UI aktualisiert sich nicht
  • notifyListeners() bei Provider vergessen → UI wird nicht aktualisiert
  • await bei asynchronen Operationen vergessen → App stürzt ab
  • ❌ Internet-Berechtigung in AndroidManifest.xml vergessen → App kann keine Netzwerkanfragen senden

Frei für alle Anfänger