美文网首页
自定义View中使用协程的一点思考

自定义View中使用协程的一点思考

作者: 梧叶已秋声 | 来源:发表于2022-11-26 17:30 被阅读0次

在activity中使用协程很方便。
在添加依赖implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'后,可以直接调用lifecycleScope.launch,无需考虑协程的管理。

https://developer.android.com/topic/libraries/architecture/coroutines?hl=zh-cn#lifecyclescope

LifecycleScope

为每个 Lifecycle 对象定义了 LifecycleScope。在此范围内启动的协程会在 Lifecycle 被销毁时取消。您可以通过 lifecycle.coroutineScopelifecycleOwner.lifecycleScope 属性访问 LifecycleCoroutineScope

如下所示。

// MainActivity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        lifecycleScope.launch{
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                repeat(Int.MAX_VALUE){
                    Log.d(TAG,"inner repeat")
                    delay(3000L)
                }

            }
        }
  }

因为AppCompatActivity继承自ComponentActivity,而ComponentActivity实现了LifecycleOwner接口,并且在适当的时机修改了Lifecycle.State。
只要自定义View实现了LifecycleOwner接口,并且修改Lifecycle.State,就可以使得View变成生命周期感知型组件。


class MyViewPager2 @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0,
) : FrameLayout(context, attrs, defStyle) , LifecycleOwner {
    private var binding: LayoutMyViewpager2Binding
    private lateinit var lifecycleRegistry: LifecycleRegistry
    
    
    init {
        Log.d(TAG,"inner init")
        binding = LayoutMyViewpager2Binding.inflate(LayoutInflater.from(context),this,true)

        addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
            // View onDetached 的时候调用 onDestroy()
            override fun onViewDetachedFromWindow(v: View?) {
                Log.d(TAG,"inner onViewDetachedFromWindow")
                // 在Lifecycle被销毁之后,协程会跟着取消
                onDestroy()
            }

            // View onAttached 的时候调用 onStart()
            override fun onViewAttachedToWindow(v: View?) {
                Log.d(TAG,"inner onViewAttachedToWindow")
                onStart()
            }
        })
    }

    fun onStart() {
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
        Log.d(TAG,"inner onStart currentState = ${lifecycleRegistry.currentState}")
    }
    
    fun onDestroy() {
        lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
    

    // 开启自动滚动
    fun autoScroll(){
        Log.d(TAG,"inner autoScroll")

        lifecycleScope.launch(exceptionHandler) {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                repeat(Int.MAX_VALUE){
                    Log.d(TAG,"inner repeat")
                    delay(3000L)
                }

            }
        }
    }

    private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
        Log.d(TAG, "CoroutineExceptionHandler exception : ${exception.message}")
    }


    // 注册
    fun register(){
        lifecycleRegistry = LifecycleRegistry(this)
        Log.d(TAG,"after lifecycleRegistry")
    }
   

}

不过我后来想想,这种写法没有必要。
其实应该写个自定义View中写个回调,在ViewModel中开启协程。还是编程思想的转变问题。

https://developer.android.com/topic/libraries/architecture/lifecycle?hl=zh-cn#use-cases

生命周期感知型组件的最佳做法

  • 设法编写数据驱动型界面,对于此类界面,界面控制器的责任是随着数据更改而更新视图,或者将用户操作通知给 ViewModel

参考链接:
使用生命周期感知型组件处理生命周期
将 Kotlin 协程与生命周期感知型组件一起使用

How to make custom view Lifecycle Aware in Android
自定义生命周期以及实现生命周期感知能力
再谈协程之Lifecycle潜行者

每日一问:浅谈 onAttachedToWindow 和 onDetachedFromWindow

RecyclerView、View的onAttachedToWindow和onDetachedFromWindow调用时机

AndroidKotlinCoroutines

相关文章

网友评论

      本文标题:自定义View中使用协程的一点思考

      本文链接:https://www.haomeiwen.com/subject/yeecfdtx.html