Appearance
Kapitel 17: Fortgeschrittene Tipps
17.1 Flutter Code-Normen
Namenskonventionen
| Element | Konvention | Beispiel |
|---|---|---|
| Klassenamen | PascalCase | MyWidget, HomePage |
| Funktionsnamen | camelCase | buildWidget(), loadData() |
| Variablenamen | camelCase | userName, isLoading |
| Konstanten | camelCase oder SCREAMING_SNAKE_CASE | PI, defaultTimeout |
| Dateinamen | snake_case | home_page.dart, user_model.dart |
| Paketnamen | lowercase_with_underscores | shared_preferences, flutter_launcher_icons |
Code-Formatierung
analysis_options.yaml konfigurieren:
yaml
include: package:flutter_lints/flutter.yaml
linter_rules:
- avoid_print # print() in Produktion vermeiden
- prefer_const_constructors # const Konstruktoren bevorzugen
- unnecessary_null_comparison # Unnötige Null-Prüfung
- always_use_package_imports # Paket-Importe verwendenCode-Organisation
Schlecht (alles in einer Datei):
dart
// main.dart - ZU VIELE VERANTWORTLICHKEITEN!
class MyApp extends StatelessWidget { ... }
class HomePage extends StatefulWidget { ... }
class LoginPage extends StatefulWidget { ... }
class ApiService { ... }Gut (Aufteilung in mehrere Dateien):
lib/
├── main.dart
├── pages/
│ ├── home_page.dart
│ └── login_page.dart
├── widgets/
│ ├── custom_button.dart
│ └── custom_card.dart
├── services/
│ └── api_service.dart
└── models/
└── user_model.dart17.2 Widget-Kapselung (Code-Wiederverwendbarkeit)
Warum Widgets kapseln?
Vorteile:
- ✅ Code-Wiederverwendbarkeit
- ✅ Bessere Lesbarkeit
- ✅ Leichtere Wartbarkeit
- ✅ Einheitliches Design
Beispiel: Benutzerdefiniertes Button-Widget
Schlecht (Code-Duplizierung):
dart
// Überall im Code wiederholt
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: const Text('Button'),
)Gut (Widget kapseln):
dart
// widgets/custom_button.dart
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback? onPressed;
final Color? color;
const CustomButton({
super.key,
required this.text,
this.onPressed,
this.color,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: color ?? Colors.blue,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: Text(text),
);
}
}
// Verwendung:
CustomButton(
text: 'Speichern',
onPressed: () {
print('Speichern geklickt');
},
)Beispiel: Benutzerdefiniertes Card-Widget
dart
// widgets/custom_card.dart
import 'package:flutter/material.dart';
class CustomCard extends StatelessWidget {
final Widget child;
final EdgeInsetsGeometry? padding;
final VoidCallback? onTap;
const CustomCard({
super.key,
required this.child,
this.padding,
this.onTap,
});
@override
Widget build(BuildContext context) {
return Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: InkWell(
onTap: onTap,
child: Padding(
padding: padding ?? const EdgeInsets.all(16),
child: child,
),
),
);
}
}
// Verwendung:
CustomCard(
onTap: () {
print('Card geklickt');
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Text('Titel', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text('Beschreibung...'),
],
),
)17.3 Performance-Optimierung (Grundlagen)
1. const Konstruktoren verwenden
Schlecht:
dart
Text('Hallo') // Jedes Mal neu erstelltGut:
dart
const Text('Hallo') // Einmal erstellt, wiederverwendet2. ListView.builder statt ListView.children verwenden
Schlecht (alle Elemente werden auf einmal erstellt):
dart
ListView(
children: List.generate(1000, (index) => ListTile(title: Text('Element $index'))),
)Gut (nur sichtbare Elemente werden erstellt):
dart
ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) => ListTile(title: Text('Element $index')),
)3. Bilder cachen (cached_network_image)
Installation:
yaml
dependencies:
cached_network_image: ^3.3.0Verwendung:
dart
CachedNetworkImage(
imageUrl: 'https://example.com/bild.jpg',
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
)4. setState() sparsam verwenden
Schlecht (gesamte Seite wird neu gebaut):
dart
void _erhoehen() {
setState(() {
_zaehler++;
_aktualisiereText(); // Unnötig, da es nicht die UI beeinflusst
});
}Gut (nur notwendige Teile aktualisieren):
dart
void _erhoehen() {
setState(() {
_zaehler++;
});
}
void _aktualisiereText() {
// Logik, die kein setState() benötigt
}5. AnimatedBuilder oder ValueListenableBuilder verwenden
Für komplexe Animationen/Zustandsänderungen:
dart
ValueListenableBuilder<int>(
valueListenable: _zaehler,
builder: (context, wert, child) {
return Text('$wert');
},
)17.4 Häufige Drittanbieter-Plugins (nach Anwendungsfall)
Netzwerk
- dio: ^5.4.0 - Leistungsstarke Netzwerk-Bibliothek
- http: ^1.1.0 - Einfache HTTP-Anfragen
Lokale Speicherung
- shared_preferences: ^2.2.0 - Key-Value-Speicherung
- sqflite: ^2.3.0 - Lokale Datenbank
- hive: ^2.2.3 - NoSQL, schnelle Leistung
UI-Komponenten
- flutter_screenutil: ^5.9.0 - Responsive Design
- flutter_swiper: ^1.1.6 - Bild-Karussell
- percent_indicator: ^4.2.3 - Fortschrittsanzeige
Zustandsverwaltung
- provider: ^6.1.1 - Empfohlen (einfach)
- get: ^4.6.5 - Einfach, beliebt
- flutter_bloc: ^8.1.2 - Für große Projekte
Andere
- image_picker: ^1.0.4 - Bilder aus Kamera/Galerie auswählen
- url_launcher: ^6.1.11 - URLs öffnen (Browser, Telefon, E-Mail)
- package_info_plus: ^4.2.0 - App-Informationen abrufen (Version, Name)
17.5 Flutter-Versionsaktualisierung & Kompatibilitätsbehandlung
Flutter-Version aktualisieren
bash
# Aktuelle Version überprüfen
flutter --version
# Auf stable Version aktualisieren
flutter upgrade
# Auf bestimmte Version wechseln
flutter version v3.16.0pubspec.yaml nach Aktualisierung anpassen
yaml
environment:
sdk: '>=3.0.0 <4.0.0' # SDK-Version anpassen
flutter: '>=3.0.0' # Flutter-Version anpassen
dependencies:
flutter:
sdk: flutter
dio: ^5.4.0 # Bibliotheksversionen überprüfenbash
# Abhängigkeiten aktualisieren
flutter pub getHäufige Kompatibilitätsprobleme
Problem: Nach der Aktualisierung treten Fehler auf.
Lösungen:
flutter cleanausführenflutter pub getausführenflutter upgrade --forceerzwingt Aktualisierungpubspec.yamlüberprüfen (Versionen anpassen)
Zusammenfassung
In diesem Kapitel haben Sie:
- ✅ Flutter Code-Normen gelernt
- ✅ Widget-Kapselung für Code-Wiederverwendbarkeit implementiert
- ✅ Performance-Optimierung (const, ListView.builder, Bild-Caching) gelernt
- ✅ Häufige Drittanbieter-Plugins kennengelernt
- ✅ Flutter-Versionsaktualisierung und Kompatibilitätsbehandlung gelernt
Nächstes Kapitel: Wir werden Flutter-Häufige Interviewfragen lernen.
Übungsaufgaben:
- Kapseln Sie ein benutzerdefiniertes Widget (z.B.
CustomAppBar) - Optimieren Sie eine Liste mit 1000 Elementen (verwenden Sie
ListView.builder) - Fügen Sie Bild-Caching mit
cached_network_imagehinzu - Aktualisieren Sie Ihr Projekt auf die neueste Flutter-Version
Häufige Fehler:
- ❌ Widgets nicht kapseln → Code-Duplizierung
- ❌
ListViewohnebuilderfür große Datenmengen verwenden → Performance-Probleme - ❌
setState()zu häufig aufrufen → Unnötige Rebuilds - ❌ Flutter-Version nicht aktualisieren → Sicherheitslücken, fehlende Funktionen
