在聊天应用程序中,需要处理图片--下载和上传。处理本身是在RxJava2的Observables的帮助下完成的;而下载或上传的命令则是在RecyclerView Adapter的OnBindViewHolder()中完成的。
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (currentlyUsedPositionToMessageMap.containsKey(position)) {
val message = currentlyUsedPositionToMessageMap[position]
when (message) {
is TextMessage -> (holder as TextMessageViewHolder).bind(message)
is ImageMessage -> (holder as ImageMessageViewHolder).bind(message)
}
} else {
val (messageType, downloadableMessage) = downloadableMessages[position]
disposables += downloadableMessage //Observable
.subscribeBy(
onNext = {
currentlyUsedPositionToMessageMap[position] = it
notifyItemChanged(position)
},
onError = {
Log.e(LOG_TAG, Log.getStackTraceString(it))
}
)
when (messageType){
"image" -> (holder as ImageMessageViewHolder).showDefaultAnimation()
"text" -> (holder as TextMessageViewHolder).showDefaultAnimation()
}
}
}
上述代码的思路是 如果图片(或文本)已经被下载,则在ViewHolder中填充数据,否则设置下载任务,并使ViewHolder显示一些默认的动画。
面临的问题是:没有能力更新可见的ViewHolder。 因为notifyItemChanged(position)会导致以下错误,所以在下载任务完成后,无法更新可见的ViewHolders。
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView
那么,如何解决这个Exception呢?换句话说。在成功下载图像后,如何更新[位置]的ViewHolder(如果可见)?
在未完全加载的RecyclerView上进行了更新,导致了异常。
当RecyclerView正在计算布局或滚动时,不能调用该方法。
注意:"本方法"指项目更新时的notifyItemChanged(position)。
问题与Imaage处理无关,而是与文本处理有关。应用程序的设计是,如果当前项目是一个可下载的图片,那么就去下载它;如果它已经是一个缓存的文本,那么就从Android主线程返回带有文本的新Observable。所以,在主线程上创建Observable的过程中,与RecyclerView ViewHolder的数据填充进行了赛跑。因此,当Observable被返回时,RecyclerView并没有被加载所有的项目,而这些项目必须在其他时间被加载,这就导致了对不完整的RecyclerView执行更新操作。因此,出现了异常