本頁提供多個架構的最佳做法和建議。採用這些最佳做法和建議,可提升應用程式的品質、穩定性和擴充性,還能更輕鬆地維護及測試應用程式。
UI 層
UI 層的作用是在螢幕上顯示應用程式資料,且為使用者與應用程式互動的主要管道。以下是 UI 層的最佳做法:
- 即使只有單一資料來源,仍應建立存放區。
- 在小型應用程式中,可以選擇將資料層類型放入
data套件或模組。
建議 |
說明 |
遵循單向資料流 (UDF)。 強烈建議 |
遵循單向資料流程 (UDF) 原則,其中 ViewModel 使用觀測器模式公開 UI 狀態,並透過方法呼叫從 UI 接收動作。 |
如果 AAC ViewModel 對您的應用程式有幫助,建議多加利用。 強烈建議 |
使用 AAC ViewModel 處理商業邏輯,並擷取應用程式資料,以便在 UI 中公開 UI 狀態。 請參閱這裡的 ViewModel 最佳做法瞭解詳情。 請參閱這裡的 ViewModel 優點。 |
使用生命週期感知方法收集 UI 狀態。 強烈建議 |
使用適合的生命週期感知協同程式建構工具 進一步瞭解 |
請勿將事件從 ViewModel 傳送至 UI。 強烈建議 |
在 ViewModel 中立即處理事件,並引起狀態更新,進而處理事件。請參閱這裡的 UI 事件瞭解詳情。 |
使用單一活動應用程式。 推薦項目 |
如果應用程式有多個畫面,請使用導覽片段前往不同畫面,以及深層連結至應用程式。 |
下列文字片段說明如何以生命週期感知方式收集 UI 狀態:
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
ViewModel 負責提供 UI 狀態和資料層存取權。以下是一些 ViewModel 最佳做法:
建議 |
說明 |
ViewModel 應不受 Android 生命週期的影響。 強烈建議 |
ViewModel 不應保留任何生命週期相關類型的參照。請勿將 |
使用協同程式和資料流。 強烈建議 |
ViewModel 透過以下方式與資料或網域層互動:
|
在畫面層級使用 ViewModel。 強烈建議 |
不要在可重複使用的 UI 中使用 ViewModel,您應在以下位置使用 ViewModel:
|
請勿使用 強烈建議 |
使用 |
公開 UI 狀態。 推薦項目 |
ViewModel 應透過名為
|
以下文字片段概述了如何從 ViewModel 公開 UI 狀態:
@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
)
// ...
}
生命週期
以下是使用 Android 生命週期的一些最佳做法:
建議 |
說明 |
不要覆寫活動或片段中的生命週期方法。 強烈建議 |
不要覆寫活動或片段中的生命週期方法,例如 |
下列文字片段概述了如何根據特定生命週期狀態來執行作業:
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) {
// ...
}
}
}
}