Konzepte und Jetpack Compose-Implementierung
Auf dieser Seite finden Sie mehrere Best Practices und Empfehlungen für die Architektur. Wenn Sie sie übernehmen, können Sie die Qualität, Robustheit und Skalierbarkeit Ihrer App verbessern. Außerdem erleichtern sie die Wartung und das Testen Ihrer App.
UI-Ebene
Die UI-Ebene dient dazu, die Anwendungsdaten auf dem Bildschirm darzustellen und als primärer Punkt für die Nutzerinteraktion zu fungieren. Hier sind einige Best Practices für die UI-Ebene:
- Sie sollten Repositories auch dann erstellen, wenn sie nur eine Datenquelle enthalten.
- In kleinen Apps können Sie die Datenebenentypen in einem
data-Paket oder -Modul platzieren.
Empfehlung |
Beschreibung |
Folgen Sie dem unidirektionalen Datenfluss (UDF). Dringend empfohlen |
Halten Sie sich an die Prinzipien des unidirektionalen Datenflusses (Unidirectional Data Flow, UDF), bei denen ViewModels den UI-Status über das Observer-Muster bereitstellen und Aktionen über Methodenaufrufe von der UI empfangen. |
Verwenden Sie AAC ViewModels, wenn die Vorteile für Ihre App gelten. Dringend empfohlen |
Verwenden Sie AAC-ViewModels, um Geschäftslogik zu verarbeiten und Anwendungsdaten abzurufen, um den UI-Status für die Benutzeroberfläche verfügbar zu machen. |
Lebenszyklusbewusste Erfassung des UI-Zustands verwenden Dringend empfohlen |
Erfassen Sie den UI-Status über die UI mit dem entsprechenden lebenszyklusbezogenen Coroutine-Builder Weitere Informationen zu |
Senden Sie keine Ereignisse vom ViewModel an die Benutzeroberfläche. Dringend empfohlen |
Verarbeiten Sie das Ereignis sofort im ViewModel und lösen Sie mit dem Ergebnis der Verarbeitung des Ereignisses eine Statusaktualisierung aus. Weitere Informationen zu UI-Ereignissen |
Verwenden Sie eine App mit nur einer Aktivität. Empfohlen |
Verwenden Sie Navigationsfragmente, um zwischen Bildschirmen zu wechseln und Deeplinks zu Ihrer App zu erstellen, wenn Ihre App mehrere Bildschirme hat. |
Im folgenden Snippet wird beschrieben, wie der UI-Zustand auf lebenszyklusbewusste Weise erfasst wird:
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Process item
}
}
}
}
}
ViewModel
ViewModels sind für die Bereitstellung des UI-Zustands und den Zugriff auf die Datenschicht verantwortlich. Hier sind einige Best Practices für ViewModels:
Empfehlung |
Beschreibung |
ViewModels sollten unabhängig vom Android-Lebenszyklus sein. Dringend empfohlen |
ViewModels sollten keine Referenz auf einen Lifecycle-bezogenen Typ enthalten. Übergeben Sie |
Verwenden Sie Coroutines und Flows. Dringend empfohlen |
Das ViewModel interagiert mit den Daten- oder Domänenebenen über:
|
ViewModels auf Bildschirmebene verwenden Dringend empfohlen |
Verwenden Sie ViewModels nicht in wiederverwendbaren UI-Elementen. ViewModels sollten in folgenden Fällen verwendet werden:
|
Verwenden Sie nicht Dringend empfohlen |
Verwenden Sie die Klasse |
UI-Zustand bereitstellen Empfohlen |
ViewModels sollten Daten über eine einzelne Property namens
|
Das folgende Snippet zeigt, wie Sie den UI-Status aus einem ViewModel bereitstellen:
@HiltViewModel
class BookmarksViewModel @Inject constructor(
newsRepository: NewsRepository
) : ViewModel() {
val feedState: StateFlow<NewsFeedUiState> =
newsRepository
.getNewsResourcesStream()
.mapToFeedState(savedNewsResourcesState)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = NewsFeedUiState.Loading
)
// ...
}
Lebenszyklus
Im Folgenden finden Sie einige Best Practices für die Arbeit mit dem Android-Lebenszyklus:
Empfehlung |
Beschreibung |
Überschreiben Sie keine Lebenszyklusmethoden in Aktivitäten oder Fragmenten. Dringend empfohlen |
Überschreiben Sie keine Lebenszyklusmethoden wie |
Das folgende Snippet zeigt, wie Sie Vorgänge in einem bestimmten Lebenszyklusstatus ausführen:
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
// ...
}
override fun onPause(owner: LifecycleOwner) {
// ...
}
}
}
}