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

Android实现下载成功后即时隐藏RecyclerView下载按钮

解决方案

要实现下载完成后即时隐藏对应条目下载按钮,核心是在异步下载完成后通知RecyclerView Adapter更新指定位置的UI,具体修改步骤如下:

1. 更新下载回调接口

修改PDFDownloadListner接口,添加带位置的下载结果回调,用于传递下载状态和对应条目位置:

interface PDFDownloadListner {
    fun onDownload(url: String?, title: String?, position: Int)
    fun onDownloadResult(position: Int, isSuccess: Boolean)
}

2. 修改DownloadHandler支持异步结果回调

原downloadFile方法的返回值无效(异步操作无法立即返回结果),改为通过自定义接口回调通知下载结果:

class DownloadHandler {
    // 定义下载结果回调接口
    interface OnDownloadResultListener {
        fun onResult(isSuccess: Boolean)
    }

    fun downloadFile(
        url: String?, 
        fileName: String, 
        context: Context, 
        filePath: File,
        resultListener: OnDownloadResultListener // 新增回调参数
    ) {
        // 原有进度弹窗、AlertDialog初始化代码保持不变

        PRDownloader.download(url, filePath.path, fileName)
            .build()
            // 原有进度、暂停等监听方法保持不变
            .start(object : OnDownloadListener {
                override fun onDownloadComplete() {
                    down = true
                    Toast.makeText(context, "Download completed ", Toast.LENGTH_SHORT).show()
                    progressDialog!!.dismiss()
                    alertDialog.show()
                    // 通知下载成功
                    resultListener.onResult(true)
                }

                override fun onError(error: Error) {
                    down = false
                    Toast.makeText(context, "Something went wrong", Toast.LENGTH_SHORT).show()
                    failed.show()
                    progressDialog!!.dismiss()
                    // 通知下载失败
                    resultListener.onResult(false)
                }
            })
    }
}

3. 修改Adapter传递下载位置并添加更新方法

在Adapter的下载按钮点击事件中传递当前条目位置,同时新增方法用于更新指定位置的UI:

class MaterialsAdapter(...) : RecyclerView.Adapter<MaterialsAdapter.ViewHolder>() {
    // 原有代码保持不变

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // 原有绑定逻辑保持不变

        holder.downloadBtn.setOnClickListener {
            listener.onDownload(
                arrayList[position].Link,
                "Ch-${arrayList[position].chNo}. ${arrayList[position].Title}",
                position // 新增传递当前条目位置
            )
        }
    }

    // 添加更新指定位置的方法
    fun updateDownloadButton(position: Int) {
        val item = arrayList[position]
        val file = File(
            "$folderLocations/Ch-${item.chNo}. ${item.Title} [twoRoot2].pdf"
        )
        // 直接找到对应ViewHolder更新视图,比notifyItemChanged更高效
        val holder = recyclerView.findViewHolderForAdapterPosition(position) as? ViewHolder
        holder?.downloadBtn?.visibility = if (file.exists()) View.GONE else View.VISIBLE
    }
}

4. Activity中处理回调并通知Adapter更新

在Activity中保存Adapter引用,接收下载回调后通知Adapter更新对应位置:

class MaterialsActivity : AppCompatActivity(), PDFDownloadListner, OnPDFSelectListener {
    private lateinit var adapter: MaterialsAdapter // 保存Adapter引用

    override fun onCreate(savedInstanceState: Bundle?) {
        // 原有初始化代码保持不变

        if (medium.equals("h")) {
            mainViewModel.hisHinLiveData.observe(this) {
                this.runOnUiThread {
                    adapter = MaterialsAdapter(
                        this, it!!.studyMaterialCS,
                        this, this, file
                    )
                    progressDialog.dismiss()
                    recyclerView.adapter = adapter
                }
            }
        } else if (medium.equals("e")) {
            mainViewModel.hisEngLiveData.observe(this) {
                this.runOnUiThread {
                    adapter = MaterialsAdapter(
                        this, it!!.studyMaterialCS,
                        this, this, file
                    )
                    progressDialog.dismiss()
                    recyclerView.adapter = adapter
                }
            }
        }
    }

    override fun onDownload(url: String?, title: String?, position: Int) {
        val fileName = "$title [twoRoot2].pdf"
        Toast.makeText(applicationContext, "Downloading....", Toast.LENGTH_SHORT).show()
        downloadHandler.downloadFile(url, fileName, this, file, object : DownloadHandler.OnDownloadResultListener {
            override fun onResult(isSuccess: Boolean) {
                if (isSuccess) {
                    // 必须在主线程更新UI
                    runOnUiThread {
                        adapter.updateDownloadButton(position)
                    }
                }
            }
        })
    }

    // 原有其他方法保持不变
}

关键说明

  • 异步下载操作无法通过返回值获取结果,必须用回调接口传递状态
  • 更新RecyclerView UI必须在主线程执行,因此需要调用runOnUiThread
  • 直接更新对应ViewHolder的视图比调用notifyItemChanged更高效,避免不必要的重绑定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:45:34