android - 取消 onViewDetachedFromWindow 内特定 ViewHolder 的特定协程
问题描述
(已编辑问题......)我正在开发一个聊天应用程序,并且有一个特定的 API,所以有些事情我必须以特定的方式实现它们。例如(以及我有问题的情况......)
当我必须显示图像时,API 说我必须将图像分成小块并将它们存储为带有 byteArray 内容的消息。还有一个header message,它的body是fileChunks的messageIds。因此,在 onBindViewHolder 内的 RecyclerView 中,当我看到头文件消息(msgType == 1)时,我启动一个协程以通过 id 获取 chunkFile 消息,构造文件然后切换到 MainDispatcher,因此图像与使用 BitmapFactory.decodeByteArray 滑动。代码如下所示
messageItem.message?.msgType == MSG_TYPE_FILE -> {
holder.sntBody.text = "Loading file"
val fileInfo = Gson().fromJson(URLDecoder.decode(messageItem.message?.body, "UTF-8"), FileInformation::class.java)
job = chatRoomAdapterScope.launch(Dispatchers.IO) {
// i get the messageIds of the chunks from Header message
val segSequence = fileInfo.seg.split(",").map { it.toLong() }
// i get the fileChunks from Database
val fileChunks = AppDatabase.invoke(mContext).messageDao().getMessageById(segSequence)
val compactFile = ByteArrayOutputStream()
// Reconstruct the file
for (chunk in fileChunks)
compactFile.write(Base64.decode(chunk.fileBody, Base64.DEFAULT))
withContext(Dispatchers.Main) {
val bitmapOptions = BitmapFactory.Options().apply {
inSampleSize = 8
}
Glide.with(mContext).asBitmap()
.load(BitmapFactory.decodeByteArray(compactFile.toByteArray(), 0, compactFile.size(), bitmapOptions)!!)
.fitCenter()
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
holder.sntImageView.setImageBitmap(resource)
holder.sntImageView.visibility = View.VISIBLE
}
})
holder.sntBody.text = fileInfo.filename
}
}
}
我的问题是,当我快速滚动时,应该在一个项目中加载的图像出现在另一个项目中。我的第一个猜测是,从特定项目开始的协程在项目被回收后并没有完成,所以当协程完成时,它引用了一个新项目,所以我添加了 holder.itemView.addOnAttachStateChangeListener 方法,正如一些人评论的那样. 然而我没有工作。是否知道为什么会发生这种情况,以及根据特定的 API 是否有更好的过程实现......?
解决方案
我认为您可以使用View.OnAttachStateChangeListener
它:
override fun onBindViewHolder() {
if(messageType == TYPE_FILE) {
val job = chatRoomAdapterScope.launch(Dispatchers.IO) {
val fileChunks = AppDatabase.invoke(MyApplication.instance).messageDao()
.getMessageByMessageId(segSequence)
// do some heacy work with the fileChunks
withContext(Dispatchers.Main) {
// holder set up
}
}
holder.itemView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewDetachedFromWindow(view: View) {
view.removeOnAttachStateChangeListener(this)
job.cancel()
}
override fun onViewAttachedToWindow(p0: View?) {}
})
}
}
推荐阅读
- javascript - 为什么 v-dialog 会重置另一个元素的可见性切换?
- deep-learning - Pytorch 迭代数据加载器两次
- powershell - Powershell 将所有输出流重定向到文件并将错误重定向到控制台
- javascript - 如何在 firebase 中编写复合查询?
- python - 如何创建函数列表,然后在另一个函数中将其用作可调用函数?
- python-3.x - TLS/SSL 套接字 python 服务器
- javascript - 反应中嵌套对象的唯一键
- sql - 我可以从一个表到另一个表有两个外键,以获得两列字段吗?
- python - 验证时将 Row 转换为 json 错误
- spring - 更改 netflix 功能区中的端口号