You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何从回调获取值实现文件下载进度展示

解决RecyclerView中获取下载回调数据的问题

核心思路

将下载状态(进度、结果)直接存储在DItem实体中,让下载回调触发时更新DItem的状态,再通知Adapter刷新列表,这样onBindViewHolder就能直接从DItem读取最新状态进行UI展示。

步骤1:修改DItem,添加状态存储字段

给DItem补充下载进度、状态、错误信息、文件对象等字段,用来持久化下载过程中的数据:

// 定义下载状态枚举,明确当前下载阶段
enum class DownloadStatus {
    WAITING, DOWNLOADING, SUCCESS, FAILURE
}

data class DItem (
    var url: String? = null,
    var progress: Int = 0,
    var status: DownloadStatus = DownloadStatus.WAITING,
    var error: Error? = null,
    var file: File? = null,
    // 状态变化回调,用于通知Adapter刷新
    var onStatusUpdated: (() -> Unit)? = null
)

步骤2:重构回调逻辑,更新DItem状态

创建DItem时,给DownloadManager传递的回调直接修改DItem的状态,并触发刷新通知:

class DownloadActivity : AppCompatActivity() {
    private lateinit var adapter: DownloadAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        adapter = DownloadAdapter()
        // 初始化示例下载项
        val downloadItem = DItem(url = "your_download_url")
        // 设置状态变化时的刷新逻辑
        downloadItem.onStatusUpdated = {
            val position = adapter.list.indexOf(downloadItem)
            if (position != -1) {
                adapter.notifyItemChanged(position)
            }
        }
        adapter.list.add(downloadItem)
        
        // 触发下载任务
        FileDownloadManager().download(downloadItem.url!!, object : FileDownloadManager.Listener {
            override fun onSuccess(file: File) {
                downloadItem.status = DownloadStatus.SUCCESS
                downloadItem.file = file
                downloadItem.onStatusUpdated?.invoke()
            }

            override fun onFailure(error: Error) {
                downloadItem.status = DownloadStatus.FAILURE
                downloadItem.error = error
                downloadItem.onStatusUpdated?.invoke()
            }

            override fun onProgress(progress: Int) {
                downloadItem.status = DownloadStatus.DOWNLOADING
                downloadItem.progress = progress
                downloadItem.onStatusUpdated?.invoke()
            }
        })
    }
}

步骤3:在Adapter中直接读取状态展示UI

此时DItem已持有最新下载数据,onBindViewHolder可以直接读取并更新列表项UI:

class DownloadAdapter : RecyclerView.Adapter<DownloadAdapter.MyViewHolder>() {
    val list = mutableListOf<DItem>()

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val item = list[position]
        // 根据不同状态更新UI
        when(item.status) {
            DownloadStatus.WAITING -> {
                holder.progressBar.visibility = View.GONE
                holder.statusTv.text = "等待下载"
            }
            DownloadStatus.DOWNLOADING -> {
                holder.progressBar.visibility = View.VISIBLE
                holder.progressBar.progress = item.progress
                holder.statusTv.text = "下载中:${item.progress}%"
            }
            DownloadStatus.SUCCESS -> {
                holder.progressBar.visibility = View.GONE
                holder.statusTv.text = "下载完成:${item.file?.name}"
            }
            DownloadStatus.FAILURE -> {
                holder.progressBar.visibility = View.GONE
                holder.statusTv.text = "下载失败:${item.error?.message}"
            }
        }
    }

    // ViewHolder定义
    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val progressBar: ProgressBar = itemView.findViewById(R.id.download_progress)
        val statusTv: TextView = itemView.findViewById(R.id.download_status)
    }
}

额外优化建议

  • 给DItem添加唯一ID字段(如id: String),替代indexOf查找位置,避免列表数据变动时索引失效。
  • 大量下载任务时,使用DiffUtil进行局部刷新,提升RecyclerView性能。
  • 在Activity销毁时取消未完成的下载任务,避免内存泄漏。

内容的提问来源于stack exchange,提问作者JSONParser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 10:52:48