Android 片段中状态流的广义函数

Android generalized function for state flow in fragment

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

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

public class AnyOfYourFragments extends AbsractFragment{

   //you do here what you want to do
   
}

在您的 AbstractFragment 中:

public abstract class AbstractFragment extends 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()
    }
}

我不知道 kotlin,所以我的代码有点混用 java 但我相信你明白了

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

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{
                ...
            }
        }
    }
}

一种新方式:

   // Start a coroutine in the lifecycle scope
    lifecycleScope.launch {
        // repeatOnLifecycle launches the block in a new coroutine every time the
        // lifecycle is in the STARTED state (or above) and cancels it when it's STOPPED.
        repeatOnLifecycle(Lifecycle.State.STARTED) {
        }
     }