この記事はKotlin Advent Calendar 2020 の24日目の記事です。
背景
以前にCoroutines Flowを使ってRxを卒業する記事を書き、Coroutine Flowのサンプルを書きましたが、その後、Flow界隈に新星が生まれました。
-
StateFlow
- subscribeで直近の値を受信する (複数回連続で値が来た場合は最新のみ受信)
- 初期値が必要
- Coroutinesの文脈で使うLiveData
- RxでいうところのBehaviorSubject
-
SharedFlow
- subscribeで値を受信する (複数回連続で来てもすべて受信)
- 以前にあったBroadcastChannelとかその辺の後継
- RxでいうところのPublishSubject
これらを使えば、RxどころかもはやLiveDataをほとんど使わずとも、Flowの世界だけでアプリを作ることができそうですよね?
というわけで、難しいことは考えずに早速基本的なアプリを作ってみたいと思います。
Sample
GithubのRepositoryを検索するアプリです。以前の記事と処理はほぼ同じ。
https://github.com/alpha2048/CoroutineStateSharedFlowTest
環境
- Coroutine v1.4.2
- (その他Retrofit、moshi、Koinの最新版)
解説
StateFlowでデータ管理する
実質LiveData
であるStateFlow
を使って、APIから取得したデータを管理します。
取得したデータをMutableStateFlow
に突っ込んでいきます。
UI側は公開されたStateFlow
をsubscribeして、取得したデータを表示します。初期値を見てプログレスバーの出し分けも行います。
StateFlow
に変換して公開する部分など、LiveData
の実装にかなり近いです。
ViewModel
class MainViewModel(
private val usecase: GetRepositoryUsecase
) : ViewModel() {
private val _repoItems: MutableStateFlow<List<RepoItemEntity>> = MutableStateFlow(emptyList())
val repoItems: StateFlow<List<RepoItemEntity>> = _repoItems
fun loadData() {
viewModelScope.launch {
usecase.execute("Coroutine", 1).collect {
val list = _repoItems.value
_repoItems.value = list + it.items
}
}
}
}
View側
lifecycleScope.launchWhenStarted {
viewModel.repoItems
.collect {
if (it.isNotEmpty()) {
binding.progress.visibility = View.INVISIBLE
adapter.setItem(it)
} else {
binding.progress.visibility = View.VISIBLE
}
}
}
SharedFlow
でイベントを送ってみる
SharedFlow
でイベント送信してみます。
(少し無理矢理な使い方ですが..😓)
OnClickListener
で、MutableSharedFlow
にItemを渡し、View側でsubscribeします。Listenerの代わりですね。
Adapter側
holder.binding.clickView.setOnClickListener {
scope.launch {
_onClick.emit(repoItem)
}
}
View側
lifecycleScope.launchWhenStarted {
adapter.onClick
.collect {
val uri = Uri.parse(it.htmlUrl)
startActivity(Intent(Intent.ACTION_VIEW, uri))
}
}
おわりに
BroadcastChannelがobsoleteになり、イベント通知などこれからどうしよう・・?となっていましたが、新しく登場した2種の使い勝手がいい感じなのでとても安心しました。
Flowはまだまだ発展途上ではありますが、ここまでくればProductionにFlowを採用するメリットもありそうだなと感じます。
みなさまもお試しいただき、もっとこういう使い方があるよ、というのがあれば是非教えてください🙏