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
相关产品推荐
相关产品推荐

