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

