Anm*_*mol 0 android kotlin kotlin-coroutines
我在视图(自定义视图)中使用协程,这些视图被添加到回收器视图中。
大部分计算(复杂且漫长)我都在协程上运行scopeIO并更新scopeMain.
但是,当这些视图添加到回收器视图时,它工作得很好,但当我快速滚动时,即使视图不再可见,作业也会在后台运行。
我不知道在哪里取消该工作。我见过的大多数示例代码都是活动中的协程,其中生命周期被正确定义。
我尝试取消其中的作业
onDetachedFromWindow,但是当我在回收器视图中快速滚动时,它会取消作业,而当视图再次附加到窗口时,它会变成空视图。
下面是我的协程声明
CustomView{
....
....
private val job = Job()
private val scopeMain = CoroutineScope(job + Dispatchers.Main)
private val scopeIO = CoroutineScope(job + Dispatchers.IO)
....
....
}
Run Code Online (Sandbox Code Playgroud)
由于上述原因,许多作业都处于活动状态,整个应用程序变得缓慢,并且在某些时候还会崩溃。
PS-是否有可能有一个可用于渲染整个 recyclerView 的作业,即所有子视图(CustomView)的相同作业,我相信 new Job() 创建导致了滞后。
我正在开发的演示项目:
已经提到过这个
您可以重写“ onViewDetachedFromWindow() ”并调用相应作业的cancel()。
当视图变得不可见并且适合您的目的时,将调用 onViewDetachedFromWindow 。
来自安卓文档:
当 RecyclerView.LayoutManager 决定不再需要附加到其父 RecyclerView 时,视图将被回收。这可能是因为它已经不再可见,或者是一组由仍附加到父 RecyclerView 的视图表示的缓存视图。如果项目视图绑定了大型或昂贵的数据(例如大型位图),那么这可能是释放这些资源的好地方。
链接在这里
override fun onViewDetachedFromWindow(holder: ViewHolder) {
holder.yourView.cancelJob()
}
Run Code Online (Sandbox Code Playgroud)
同样,当您的视图再次出现时:
onViewAttachedToWindow(holder:ViewHolder)
Run Code Online (Sandbox Code Playgroud)
将被调用。这里你必须重新启动协程作业。
holder.yourJob.start()
Run Code Online (Sandbox Code Playgroud)
您的问题的原因是,您正在取消作业,但是当再次查看时(它不会再次创建,它正在被重新使用,即绑定已完成到已创建的视图),因此您需要开始工作由你自己承担。
谷歌的文档说:
当此适配器创建的视图已附加到窗口时调用。这可以用作视图即将被用户看到的合理信号。如果适配器之前在 onViewDetachedFromWindow 中释放了任何资源,则应在此处恢复这些资源。
链接在这里
现在向您提出建议:
整个回收商的 OneJob:
您的作业位于视图内,因此当创建视图时,作业就会执行。为了让您拥有一份工作,您的工作应该存在于自定义视图之外。您的方法应该接受视图,并且视图应该将视图元素的创建/初始化委托给该方法。这也意味着,您需要向此外部方法公开视图内部。对我来说听起来不太优雅。另外,如果有 7 个可见项目,您的这个“外部”方法将负责渲染所有 7 个元素,这也会影响快速滚动时的性能,因为对于相当大小的列表,该方法很快就会被淹没。
| 归档时间: |
|
| 查看次数: |
2915 次 |
| 最近记录: |