首页 > 解决方案 > Fragment中状态流的Android通用函数

问题描述

我在我的应用程序中使用StateFlow,在我的应用程序中我Fragment使用它来 -

private var job: Job? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        job = lifecycleScope.launchWhenResumed {
            viewModel.getData().collect {
                // ...
            }
        }
    }

    override fun onPause() {
        job?.cancel()
        super.onPause()
    }

如您所见,我取消了onPause. 我怎么能使用一个通用函数,这样我就可以避免job?.cancel在每个片段中都这样做。

我不喜欢使用BaseFragment

标签: androidkotlinkotlin-coroutines

解决方案


一个简单的解决方案是利用片段生命周期在暂停时自动取消作业。

fun CoroutineScope.launchUntilPaused(lifecycleOwner: LifecycleOwner, block: suspend CoroutineScope.() -> Unit){
    val job = launch(block = block)
    lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
        override fun onPause(owner: LifecycleOwner) {
            job.cancel()
            lifecycleOwner.lifecycle.removeObserver(this)
        }
    })
}

//Usage
class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        lifecycleScope.launchUntilPaused(this){
            someFlow.collect{
                ...
            }
        }
    }
}

如果每个片段有很多这样的工作,我建议改用自定义CoroutineScope,以避免有许多生命周期观察者处于活动状态。

class CancelOnPauseScope(lifecycleOwner: LifecycleOwner): CoroutineScope by MainScope(){
    init{
        lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver{
            override fun onPause(owner: LifecycleOwner) {
                cancel()
                lifecycleOwner.lifecycle.removeObserver(this)
            }
        })
    }
}

class MyFragment: Fragment() {
    private val scope = CancelOnPauseScope(this)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        scope.launch{
            someFlow.collect{
                ...
            }
        }
    }
}

推荐阅读