0

我有一个回收器适配器,它在滚动时从网络加载内容(包括缩略图和其他一些数据)。

但是,当我滚动很长的距离时,适配器会尝试将请求排队,以便加载起点和点之间的所有项目,然后在新位置的项目之前显示。当它们像这样快速滚动过去时,我不想继续加载这些中间项目。

我尝试编写以下代码来执行此操作:

class SomeRecyclerAdapter(private val dataset: MutableList<SomeData>)
    : RecyclerView.Adapter<SongsRecylerAdapter.ViewHolder>() {

    // ... irrelevant fields here

    var requestInFlight: Job? = null
    var requestInFlight2: Job? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val someListItem = LayoutInflater.from(parent.context)
                .inflate(R.layout.list_item_foo, parent, false)

        return ViewHolder(someListItem)
    }

    override fun getItemCount() = dataset.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val someData = dataset[position]
        holder.someView.text = someData.toString()
        holder.thumbnailView.imageResource = R.drawable.default_thumbnail

        // Cancel any requests currently in flight, to prevent janky stuff on long scrolls
        // Otherwise, if scrolling far, it will load all of the data in sequence
        // We don't want to load the stuff in between before loading the stuff where we are at
        requestInFlight?.cancel()
        requestInFlight2?.cancel()

        requestInFlight = async(UI) {
            var someDataFromServer = listOf<Bar>()

            async(CommonPool) {
                someDataFromServer = someSuspendMethod()
            }.await()

            someData.thumbnailUri = someDataFromServer.thumbnailUri

            GlideApp.with(holder.thumbnailView.context)
                    .load(dataset[position].thumbnailUri)
                    .placeholder(R.drawable.default_thumbnail)
                    .into(holder.thumbnailView)
        }
    }

    // Viewholder here...

}

所以,我想我知道为什么它不起作用。当我取消飞行中的工作时,我真的取消了之前启动的调用,而不是正在重新加载的回收器视图元素的调用。但是,我不确定如何将作业与此元素相关联,这样当此视图被回收时,它会取消它自己的飞行请求。

有什么帮助吗?

4

1 回答 1

1

MakerequestInFlightrequestInFlight2intoViewHolder字段,因为每个字段都有自己的加载,因为现在您在滚动期间错误地覆盖了 Jobs。

然后将您的取消逻辑移动到onViewRecycled

override fun onViewRecycled(holder: ViewHolder){
    holder.requestInFlight?.cancel()
    holder.requestInFlight2?.cancel()
}

请注意,协程对它们在异步块中引用的任何对象都持有强引用,因此您可能会在屏幕旋转时泄漏上下文。

于 2018-07-04T18:03:36.983 回答