1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AndroidでFlow<T>をcollectするのをちょっとだけ楽にする

Last updated at Posted at 2021-06-18

AndroidでFlow<T>を扱う際の小ネタです。

前置き

Android+KotlinでStateFlow<T>SharedFlow<T>などをLiveData<T>代わりに利用する際は、
主にActivity/Fragment上でlifecycleScope.launchWhenStarted {}などを使ってcollect {}を実行することが多いと思います。
その際、LiveData<T>に比べてコルーチンスコープを開始する関係上ネストが一段深くなってしまいます。

Activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    lifecycleScope.launchWhenStarted {
        viewModel.flow.collect {
            binding.textView.text = it
        }
    }
}

いくつもcollectが並ぶとLiveData<T>に比べて微妙に可読性が下がるのでネストが深くならないように簡単に対策してみます。

Flow<T>の拡張関数を作って対処する

下記のような拡張関数を用意して、launch関数でネストさせなくてもcollect出来るようにしてみます。

FlowCollector.kt
inline fun <T> Flow<T>.collectWhenCreated(lifecycleOwner: LifecycleOwner, crossinline action: suspend (value: T) -> Unit): Job {
    return lifecycleOwner.lifecycleScope.launchWhenCreated {
        collect(action)
    }
}

inline fun <T> Flow<T>.collectWhenStarted(lifecycleOwner: LifecycleOwner, crossinline action: suspend (value: T) -> Unit): Job {
    return lifecycleOwner.lifecycleScope.launchWhenStarted {
        collect(action)
    }
}

inline fun <T> Flow<T>.collectWhenResumed(lifecycleOwner: LifecycleOwner, crossinline action: suspend (value: T) -> Unit): Job {
    return lifecycleOwner.lifecycleScope.launchWhenResumed {
        collect(action)
    }
}

launchWhenStarted+collectを置き換える

先程の拡張関数を使うと下記のように表すことができます。
一段ネストが減りましたね!

Activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    viewModel.flow.collectWhenStarted(this) {
        binding.textView.text = it
    }
}
Fragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel.flow.collectWhenStarted(viewLifecycleOwner) {
        binding.textView.text = it
    }
}

通常のFlow<T>の扱いと同様に、FragmentでViewの更新をする場合は引数にthisではなくviewLifecycleOwnerを指定する必要があるのでご注意下さい。
たったこれだけですが地味に便利なので試してみて下さい :bulb:

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?