【问题标题】:Create coroutine inside onBindViewHolder creates a mess在 onBindViewHolder 内部创建协程会造成混乱
【发布时间】:2019-09-17 16:47:38
【问题描述】:

我正在开发一个聊天应用程序,并且有一个特定的 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 是否有更好的过程实现......?

【问题讨论】:

标签: android android-recyclerview kotlin-coroutines


【解决方案1】:

您可以在override fun onViewRecycled(holder: EventViewHolder)中取消协程。

【讨论】:

    猜你喜欢
    • 2015-12-08
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多