#はじめに
こちらの続きです。
前回は、UI Layerを責務の分離において「表示」を担当すると簡略化して表現しましたが、今回はそれに関して詳しく見ていきます。
###対象
- 忙しくてアーキテクチャガイドを読んでいる暇などない人
- Androidにおいて、推奨されるアーキテクチャを知りたい方
- アーキテクチャガイドを読んだけども、何を言っているのか分からなかった人
#目次
内容は次の4つです。
###・UI状態の定義
###・データフローについて
###・データの監視
###・データの更新
#UIレイヤーでやること(手順)
ここでは、ニュース記事をAPIから取得するアプリを例に出しています。
##UI状態の定義
UIが保持するデータやロジック+UIコンポーネントでUIが構成されていることを示しています。
data class NewsUiState(
val isSignedIn: Boolean = false,
val isPremium: Boolean = false,
val newsItems: List<NewsItemUiState> = listOf(),
val userMessages: List<Message> = listOf()
)
data class NewsItemUiState(
val title: String,
val body: String,
val bookmarked: Boolean = false,
...
)
読み込みプロパティをデータクラスに渡しています。
これにより、状態に関するデータを保証でき、本来の責務である「表示」に集中することが出来ます。
また、不変性が担保されてないと、データレイヤーと競合をおこす可能性があります。
#データフローについて
単一データフロー(UDF)が好ましいです。(理由は後ほど説明)
上方向には、イベント通知、データソースの変更。
下方向には、データの更新、UI状態を渡す。
行われていることは下記の連続です。
- UIは、ViewModelにイベントを通知する
- ViewModelがユーザーアクションを処理して、保持しているデータを更新する
- 更新されたデータは、UIに反映させる
#ロジックの仕分け
- ビジネスロジック(状態の変化を保存) -> Data Layer
- UIロジック(状態の変化をUIに表示させる)-> UI Layer(State holder)
#UDFにする理由
- データに一貫性を持たせる
- ViewModelに状態を分けているので、UIテスト可能(?)
- 状態の変化は、ユーザーイベントかデータソースの両方なので、責務が明確に切り分けられており、メンテナンスが用意
#状態の公開
ここは、State holder -> UI elementsのデータフローについてです。
今までは、LiveDataが具体例に出てきましたが、改定後はKotlin Flowが登場してますね。
どちらかの監視可能なデータを用いることで、状態の更新とUIの更新を同期させることを目指します。
class NewsViewModel(
private val repository: NewsRepository,
...
) : ViewModel() {
private val _uiState = MutableStateFlow(NewsUiState())
val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()
private var fetchJob: Job? = null
fun fetchArticles(category: String) {
fetchJob?.cancel()
fetchJob = viewModelScope.launch {
try {
val newsItems = repository.newsItemsForCategory(category)
_uiState.update {
it.copy(newsItems = newsItems)
}
} catch (ioe: IOException) {
// Handle the error and notify the UI when appropriate.
_uiState.update {
val messages = getMessagesFromThrowable(ioe)
it.copy(userMessages = messages)
}
}
}
}
}
#その他注意点
- ViewModelはUIスレッドから安全に呼び出せるようにスレッドセーフティにする
- 長時間処理をバックグランドスレッドに移すのもViewModelの責務
-
PagingData
には、不変のアイテムが含まれるので独自のストリームを作成する(?)
#おわりに
いかがでしょうか。
全てを理解するのが難しかったので、飛ばし飛ばしになりました。
次回はData Layerについてまとめます。