Flutter Best Practices
In diesem Abschnitt werden Best Practices und Codierungsstandards in der Flutter-Entwicklung vorgestellt.
Code-Standards
Namenskonventionen
| Type | Regeln | Beispiel |
|---|---|---|
| Klassenname | UpperCamelCase | MyHomePage |
| Funktionen/Variablen | lowerCamelCase | userName, getData |
| Konstanten | Upper Camel Case + k-Präfix | kMaxCount |
| Datei | Kleinschreibung + Unterstrich | my_home_page.dart |
Beispiel: Korrekte Benennung
// Klassenname - UpperCamelCase
class UserProfilePage extends StatelessWidget {}
// Funktion - lowerCamelCase
void fetchUserData() {}
// Variable - lowerCamelCase
String userName = 'Zhang San';
// Konstanten - k-Präfix
const int kMaxRetryCount = 3;
const String kAppName = 'My App';
// Enum - UpperCamelCase
enum AppState { loading, success, error }
// Dateiname - snake_case
// user_profile_page.dart
class UserProfilePage extends StatelessWidget {}
// Funktion - lowerCamelCase
void fetchUserData() {}
// Variable - lowerCamelCase
String userName = 'Zhang San';
// Konstanten - k-Präfix
const int kMaxRetryCount = 3;
const String kAppName = 'My App';
// Enum - UpperCamelCase
enum AppState { loading, success, error }
// Dateiname - snake_case
// user_profile_page.dart
Leistungsoptimierung
1. Unnötige Rebuilds vermeiden
Beispiel: Verwendung des const-Konstruktors
// Empfohlen: const verwenden, um Rebuilds zu reduzieren
const Text('Hello') // Wird nicht neu aufgebaut
const SizedBox(width: 10)
// Vermeiden: Jeder Build erstellt ein neues Objekt
Text('Hello') // Wird neu aufgebaut
// const in Listen verwenden
ListView(
children: const [
Text('A'),
Text('B'),
Text('C'),
],
)
const Text('Hello') // Wird nicht neu aufgebaut
const SizedBox(width: 10)
// Vermeiden: Jeder Build erstellt ein neues Objekt
Text('Hello') // Wird neu aufgebaut
// const in Listen verwenden
ListView(
children: const [
Text('A'),
Text('B'),
Text('C'),
],
)
2. Verwende Keys zur Optimierung der Listen-Performance
Beispiel: Keys korrekt verwenden
// Eindeutige Keys zu Listenelementen hinzufügen
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
key: ValueKey(items[index].id), // Eindeutige Identifikatoren als Keys verwenden
title: Text(items[index].name),
);
},
)
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
key: ValueKey(items[index].id), // Eindeutige Identifikatoren als Keys verwenden
title: Text(items[index].name),
);
},
)
3. Lazy Loading von Listenelementen
Beispiel: Verwendung von ListView.builder
// Empfohlen: builder für Lazy Loading verwenden
ListView.builder(
itemCount: 1000, // Muss für große Listen verwendet werden
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
// Vermeiden: children zum Erstellen großer Listen verwenden
ListView(
children: List.generate(1000, (i) => Text('Item $i')),
)
ListView.builder(
itemCount: 1000, // Muss für große Listen verwendet werden
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
// Vermeiden: children zum Erstellen großer Listen verwenden
ListView(
children: List.generate(1000, (i) => Text('Item $i')),
)
Projektstruktur
Beispiel: Empfohlene Projektstruktur
// lib/
// ├── main.dart # Einstiegsdatei
// ├── app.dart # App-Konfiguration
// ├── core/ # Kernfunktionalität
// │ ├── constants/ # Konstanten
// │ ├── theme/ # Design
// │ ├── utils/ # Hilfsklassen
// │ └── extensions/ # Erweiterungen
// ├── data/ # Datenschicht
// │ ├── models/ # Datenmodelle
// │ ├── repositories/ # Repositories
// │ └── services/ # Netzwerkdienste
// ├── domain/ # Domänenschicht
// │ └── entities/ # Entitäten
// ├── presentation/ # Präsentationsschicht
// │ ├── pages/ # Seiten
// │ ├── widgets/ # Widgets
// │ └── providers/ # Zustandsverwaltung
// └── routes/ # Routen
// ├── main.dart # Einstiegsdatei
// ├── app.dart # App-Konfiguration
// ├── core/ # Kernfunktionalität
// │ ├── constants/ # Konstanten
// │ ├── theme/ # Design
// │ ├── utils/ # Hilfsklassen
// │ └── extensions/ # Erweiterungen
// ├── data/ # Datenschicht
// │ ├── models/ # Datenmodelle
// │ ├── repositories/ # Repositories
// │ └── services/ # Netzwerkdienste
// ├── domain/ # Domänenschicht
// │ └── entities/ # Entitäten
// ├── presentation/ # Präsentationsschicht
// │ ├── pages/ # Seiten
// │ ├── widgets/ # Widgets
// │ └── providers/ # Zustandsverwaltung
// └── routes/ # Routen
Fehlerbehandlung
Beispiel: Globale Fehlerbehandlung
void main() {
// Globale Ausnahmenerfassung
FlutterError.onError = (details) {
// Fehler protokollieren
print('Flutter Error: ${details.exception}');
// Fehler an Server melden
reportError(details.exception);
};
// Zonen-Ausnahmenerfassung
runZonedGuarded(() {
runApp(const MyApp());
}, (error, stackTrace) {
print('Zone Error: $error');
reportError(error);
});
}
// Globale Ausnahmenerfassung
FlutterError.onError = (details) {
// Fehler protokollieren
print('Flutter Error: ${details.exception}');
// Fehler an Server melden
reportError(details.exception);
};
// Zonen-Ausnahmenerfassung
runZonedGuarded(() {
runApp(const MyApp());
}, (error, stackTrace) {
print('Zone Error: $error');
reportError(error);
});
}
Weitere ErweiterungenDie Befolgung bewährter Methoden kann Code wartbarer machen, die Leistung verbessern und Fehler in der Produktion reduzieren.