Android开发:删除全部列表项后界面仍显示1条数据,如何修复?
Android列表删除最后一项后界面未更新问题
我是Android开发新手,目前除一处问题外其他功能均正常。删除列表项操作在技术层面有效,但删除最后一项时,数据已从数据库移除,却仍显示在Activity界面上,仅重启应用后才会消失。我希望无需重启应用,删除最后一项后界面就能正确显示空列表。
相关代码
Repository代码
private val mWebsDao: WebDao private val executorService: ExecutorService = Executors.newSingleThreadExecutor() init { val db = WebRoomDatabase.getDatabase(application) mWebsDao = db.webDao() } fun deleteWeb(web: Web) { executorService.execute { mWebsDao.deleteWebById(web) } }
ViewModel代码
private val mWebRepository: WebRepository = WebRepository(application) fun deleteWeb(web: Web) { mWebRepository.deleteWeb(web) }
Adapter代码
override fun onBindViewHolder(holder: ViewHolder, position: Int) { val (_, webName, webUrl, webImgColor) = listWeb[position] holder.binding.imgColorWeb.background = ColorDrawable(android.graphics.Color.rgb(webImgColor.r, webImgColor.g, webImgColor.b)) holder.binding.tvWebName.text = webName holder.binding.tvWebLink.text = webUrl holder.binding.tvCharWebName.text = webName holder.itemView.setOnClickListener { onItemClickCallback.onItemClicked(listWeb[holder.adapterPosition]) } holder.itemView.setOnLongClickListener { val popUpMenu = PopupMenu(holder.itemView.context, holder.itemView) popUpMenu.inflate(R.menu.menu_popup_item_pressed) popUpMenu.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.action_edit -> { onItemLongClickCallback.onItemLongClickedEdit(listWeb[holder.adapterPosition]) true } R.id.action_delete -> { onItemLongClickCallback.onItemLongClickedDelete(listWeb[holder.adapterPosition]) notifyItemRemoved(holder.adapterPosition) true } else -> false } } popUpMenu.show() true } } override fun getItemCount() = listWeb.size interface OnItemClickCallback { fun onItemClicked(web: Web) } interface OnItemLongClickCallback { fun onItemLongClickedEdit(web: Web) fun onItemLongClickedDelete(web: Web) }
Activity代码
override fun onItemLongClickedDelete(web: Web) { mainViewModel.deleteWeb(web) Snackbar.make(binding.root, getString(R.string.deleted_web_message), Snackbar.LENGTH_LONG) .setAction(getString(R.string.undo)) { mainViewModel.insertWeb(web) } .show() }
列表展示代码
mainViewModel.getAllWebs().observe(this) { if (it.isNullOrEmpty()) { binding.emptyListInfo.alpha = 1f } else { binding.emptyListInfo.alpha = 0f val webs = webList(it) val rvWeb = binding.rvListWeb rvWeb.layoutManager = LinearLayoutManager(this@MainActivity) webAdapter = WebAdapter(webs) rvWeb.adapter = webAdapter } }
解决方案
1. 给Adapter添加数据源更新方法
避免每次新建Adapter,改为更新现有Adapter的数据源:
class WebAdapter(private var listWeb: List<Web>) : RecyclerView.Adapter<WebAdapter.ViewHolder>() { // ... 保留原有代码 fun updateData(newList: List<Web>) { listWeb = newList notifyDataSetChanged() } // ... 保留原有代码 }
2. 优化LiveData观察逻辑
确保数据为空时也更新Adapter,同时LayoutManager只初始化一次:
mainViewModel.getAllWebs().observe(this) { webs -> val isEmpty = webs.isNullOrEmpty() binding.emptyListInfo.alpha = if (isEmpty) 1f else 0f val rvWeb = binding.rvListWeb // 仅首次初始化LayoutManager和Adapter if (rvWeb.layoutManager == null) { rvWeb.layoutManager = LinearLayoutManager(this@MainActivity) webAdapter = WebAdapter(emptyList()) rvWeb.adapter = webAdapter } // 转换数据并更新Adapter val convertedWebs = if (isEmpty) emptyList() else webList(webs) webAdapter.updateData(convertedWebs) }
3. 移除Adapter中手动的通知更新
因为Room的LiveData会自动监听数据库变化并通知界面,手动调用notifyItemRemoved会造成更新冲突:
// Adapter中删除这行代码 // notifyItemRemoved(holder.adapterPosition)
4. 确认Dao方法返回LiveData
确保Dao的查询方法返回LiveData<List<Web>>,这样数据库变化时才能自动触发界面更新:
@Dao interface WebDao { @Query("SELECT * FROM webs") fun getAllWebs(): LiveData<List<Web>> @Delete fun deleteWebById(web: Web) }
完成以上修改后,删除最后一项时,数据库数据清空,LiveData会推送空列表,Adapter更新数据源为空,RecyclerView会自动清空并显示预设的空状态界面,无需重启应用。
内容的提问来源于stack exchange,提问作者Ridhwanafzn
相关产品推荐
相关产品推荐

