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) {
}
}
我在我的应用程序和 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) {
}
}