Android 在onViewDetachedFromWindow中取消特定ViewHolder的特定协同路线
(经编辑的问题……) 我正在开发一个聊天应用程序,有一个特定的API,所以有些事情我必须以特定的方式实现它们。例如(在我有问题的情况下…) 当我必须显示一个图像时,API说我必须将图像分成小块,并将它们存储为带有byteArray内容的消息。还有一个头消息,它的主体是filechunk的messageid。因此,在onBindViewHolder内部的RecyclerView中,当我看到头文件消息(msgType==1)时,我启动一个协同程序,通过ID获取chunkFile消息,构造文件,然后切换到MainDispatcher,然后使用BitmapFactory.decodeByteArray使用Glide创建图像。代码如下所示Android 在onViewDetachedFromWindow中取消特定ViewHolder的特定协同路线,android,kotlin,android-recyclerview,kotlin-coroutines,Android,Kotlin,Android Recyclerview,Kotlin Coroutines,(经编辑的问题……) 我正在开发一个聊天应用程序,有一个特定的API,所以有些事情我必须以特定的方式实现它们。例如(在我有问题的情况下…) 当我必须显示一个图像时,API说我必须将图像分成小块,并将它们存储为带有byteArray内容的消息。还有一个头消息,它的主体是filechunk的messageid。因此,在onBindViewHolder内部的RecyclerView中,当我看到头文件消息(msgType==1)时,我启动一个协同程序,通过ID获取chunkFile消息,构造文件,然后切
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
}
}
}
messageItem.message?.msgType==MSG\u TYPE\u文件->{
holder.sntBody.text=“正在加载文件”
val fileInfo=Gson().fromJson(urldecker.decode(messageItem.message?.body,“UTF-8”),FileInformation::class.java)
job=聊天室适配器scope.launch(Dispatchers.IO){
//我从头消息中获取块的messageid
val segSequence=fileInfo.seg.split(“,”).map{it.toLong()}
//我从数据库中获取文件块
val fileChunks=AppDatabase.invoke(mContext.messageDao().getMessageById(segSequence)
val compactFile=ByteArrayOutputStream()
//重建文件
for(文件块中的块)
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(对象:SimpleTarget(){
覆盖资源就绪(资源:位图,转换:转换?){
holder.sntImageView.setImageBitmap(资源)
holder.sntImageView.visibility=View.VISIBLE
}
})
holder.sntBody.text=fileInfo.filename
}
}
}
我的问题是,当我快速滚动时,应该加载到某个项目中的图像会出现在另一个项目中。我的第一个猜测是,从某个特定项目开始的协同程序并没有在该项目回收后立即完成,因此当协同程序完成时,它引用了一个新项目,因此我添加了
holder.itemView.addOnAttachStateChangeListener方法,正如一些人评论的那样。但是我没有工作。
是否知道为什么会发生这种情况,以及根据特定的API是否有更好的过程实现…?我认为您可以使用
查看。OnAtachStateChangeListener
:
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?) {}
})
}
}
我不知道那个技巧。我会试试看,让你知道。。!谢谢你,我的朋友。我建议你从适配器中取出该协程,并在presenter/viewmodel中编写代码,然后再进行渲染。最好的解决方案是将该协程移出适配器。但是如果你想用性能和回收来交换,那么你可以用:holder.setIsRecyclable(false)来禁用它。有没有一个简单的代码示例,我从你们那里得到的,因为我是一个协同程序和其他东西的乞丐。。。?顺便说一句,有很多!!