Appearance
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 SDKUrsache:
- Android SDK nicht installiert oder Pfad nicht korrekt konfiguriert
Lösung:
- Android Studio installieren
ANDROID_HOMEUmgebungsvariable 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"' >> ~/.bashrcflutter doctor --android-licensesausführen
Problem: Emulator startet nicht
Ursache:
- HAXM nicht installiert (Intel-CPUs)
- Zu wenig Speicher
Lösung:
- Android Studio → SDK Manager → SDK Tools → Intel x86 Emulator Accelerator installieren
- 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
RowoderColumnhat 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 URLRichtig:
dart
final response = await dio.get('https://example.com'); // RICHTIGProblem: 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:
- Überprüfen Sie die JSON-Struktur der API-Antwort
- Stellen Sie sicher, dass Ihre Dart-Klasse mit dem JSON übereinstimmt
- 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.propertiesexistiert - Pfad in
build.gradlekorrekt
Beispiel (android/key.properties):
properties
storePassword=ihr_passwort
keyPassword=ihr_passwort
keyAlias=key
storeFile=d:/key.jks # Pfad zum key.jksBeispiel (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.xmlfür Android bearbeitenInfo.plistfü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:
flutter_launcher_iconsPlugin verwenden- Manuell in
android/app/src/main/res/undios/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_icons16.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 devtools5. VS Code Debugging
- Haltepunkt setzen (roter Punkt links neben Zeilennummer)
F5drücken oder "Run → Start Debugging"- Debug-Konsole verwenden, um Variablen zu inspizieren
6. Android Studio Debugging
- Haltepunkt setzen
- "Debug" Button drücken (grüner Käfer)
- 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:
- Beheben Sie einen Layout-Überlauf-Fehler in einer bestehenden App
- Implementieren Sie Zustandsverwaltung mit Provider und beheben Sie
notifyListeners()-Vergessen-Fehler - Beheben Sie einen Netzwerkrequest-Fehler (falsche URL, vergessenes
await) - Beheben Sie einen JSON-Parsing-Fehler (Struktur stimmt nicht überein)
- 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 - ❌
awaitbei asynchronen Operationen vergessen → App stürzt ab - ❌ Internet-Berechtigung in
AndroidManifest.xmlvergessen → App kann keine Netzwerkanfragen senden
