Kotlin安卓MoviesApp实现收藏功能时RecyclerView Adapter适配问题
解决方案
你只需要对现有代码做如下几处修改即可实现功能:
1. 扩展Adapter的回调接口
修改MoviesListAdapter中的OnItemClickListener,新增收藏点击的回调方法:
interface OnItemClickListener { fun onItemClick(movie: MoviesResults.Movies) // 新增收藏状态变化回调 fun onFavoriteClick(movie: MoviesResults.Movies, isChecked: Boolean) }
2. 修改ViewHolder的复选框点击逻辑
在MoviesListViewHolder的复选框点击事件中获取对应电影实例,同步更新选中状态,回调给外部处理:
init { checkbox.setOnClickListener { val position = bindingAdapterPosition // 过滤无效位置 if (position == RecyclerView.NO_POSITION) return@setOnClickListener // 获取当前位置对应的电影实例 val currentMovie = getItem(position) ?: return@setOnClickListener // 更新选中状态存储 checkBoxStateArray.put(currentMovie.id, checkbox.isChecked) // 回调给外部处理数据库操作 listener.onFavoriteClick(currentMovie, checkbox.isChecked) if (checkbox.isChecked) { showToast("电影已添加到收藏") } else { showToast("电影已从收藏移除") } } }
3. 优化复选框绑定逻辑(解决滑动复用错位问题)
修改onBindViewHolder中的状态绑定逻辑,用电影ID作为存储key避免列表变化导致的状态错位:
override fun onBindViewHolder(holder: MoviesListViewHolder, position: Int) { val currentItem = getItem(position) if (currentItem != null) { // 用电影ID读取选中状态 holder.checkbox.isChecked = checkBoxStateArray.get(currentItem.id, false) holder.bind(currentItem) } }
注:你可以删除原来的基于position的状态判断逻辑,改用上述基于电影ID的判断更稳妥
4. 在Fragment/Activity中实现收藏回调
在初始化Adapter的位置实现新增的onFavoriteClick方法,调用ViewModel的方法操作数据库:
val adapter = MoviesListAdapter(object : MoviesListAdapter.OnItemClickListener { override fun onItemClick(movie: MoviesResults.Movies) { // 原有条目点击逻辑保持不变 } override fun onFavoriteClick(movie: MoviesResults.Movies, isChecked: Boolean) { // 用页面生命周期协程执行数据库挂起操作 lifecycleScope.launch { if (isChecked) { viewModel.favoriteMovies(movie) } else { viewModel.deleteMovies(movie) } } } }, repository)
可选优化建议
- 可以移除Adapter构造函数中传入的
MoviesRepository实例,所有数据操作都通过回调交给ViewModel处理,降低耦合 - 后续可以在
MoviesResults.Movies实体中新增isFavorite字段,进入列表时先查询本地收藏表同步所有电影的收藏状态,这样每次打开APP都能正确显示已收藏的电影,无需手动维护选中状态数组
内容的提问来源于stack exchange,提问作者Ahmadddd4
相关产品推荐
相关产品推荐

