Android电商APP:从另一Fragment的Adapter刷新RecyclerView Fragment
嘿,这个场景我做电商类App的时候也碰到过,结合你的架构(两个Fragment、索引式心愿单存储),给你梳理几个靠谱的解决方案:
方案1:共享ViewModel(Jetpack推荐规范方案)
这是最贴合Android现代架构的方式,同属一个Activity的Fragment可以共享同一个ViewModel实例,数据和状态传递会非常清晰,还能避免内存泄漏问题。
实现步骤:
创建共享ViewModel
里面维护全商品列表、心愿单索引列表,还有用于通知刷新的LiveData(支持单item精准刷新):class ShopSharedViewModel : ViewModel() { // 全商品列表 val allProducts = MutableLiveData<List<Product>>() // 心愿单索引列表 val wishlistIndexes = MutableLiveData<MutableList<Int>>() // 通知Shop Fragment刷新指定item的信号 val refreshShopItem = MutableLiveData<Int?>() // 移除心愿单商品的方法 fun removeFromWishlist(targetIndex: Int) { val currentWishlist = wishlistIndexes.value ?: mutableListOf() currentWishlist.remove(targetIndex) wishlistIndexes.postValue(currentWishlist) // 发送刷新信号 refreshShopItem.postValue(targetIndex) } }Shop Fragment中观察ViewModel
通过activityViewModels()获取共享ViewModel实例,监听刷新信号并更新RecyclerView:class ShopFragment : Fragment() { private lateinit var viewModel: ShopSharedViewModel private lateinit var productAdapter: ProductAdapter override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // 获取共享ViewModel viewModel = ViewModelProvider(requireActivity())[ShopSharedViewModel::class.java] // 初始化Adapter和RecyclerView... // 监听刷新信号,精准刷新对应item viewModel.refreshShopItem.observe(viewLifecycleOwner) { index -> index?.let { productAdapter.notifyItemChanged(it) // 重置信号,避免重复触发 viewModel.refreshShopItem.postValue(null) } } return inflater.inflate(R.layout.fragment_shop, container, false) } }Wishlist Adapter中调用ViewModel方法
当用户操作心愿单(比如移除商品)时,直接调用ViewModel的方法更新数据并触发刷新:class WishlistAdapter(private val viewModel: ShopSharedViewModel, private val wishlistIndexes: List<Int>) : RecyclerView.Adapter<WishlistAdapter.ViewHolder>() { // ... 其他Adapter基础代码 inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(productIndex: Int) { // 从全商品列表中通过索引获取商品数据 val targetProduct = viewModel.allProducts.value?.get(productIndex) ?: return // 绑定商品名称、图片等数据... // 移除按钮点击事件 itemView.btn_remove_from_wishlist.setOnClickListener { viewModel.removeFromWishlist(productIndex) } } } }
方案2:接口回调(传统但直观的方式)
如果暂时不想引入ViewModel,也可以用接口回调实现跨Fragment的通信,逻辑简单易懂。
实现步骤:
定义刷新回调接口
interface OnWishlistChangeListener { fun onWishlistItemUpdated(productIndex: Int) }Shop Fragment实现接口
class ShopFragment : Fragment(), OnWishlistChangeListener { private lateinit var productAdapter: ProductAdapter override fun onWishlistItemUpdated(productIndex: Int) { // 精准刷新对应商品item productAdapter.notifyItemChanged(productIndex) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 把当前实例传递给Wishlist Fragment val wishlistFragment = parentFragmentManager.findFragmentById(R.id.fragment_wishlist) as? WishlistFragment wishlistFragment?.setWishlistChangeListener(this) } }Wishlist Fragment持有接口实例
class WishlistFragment : Fragment() { private var listener: OnWishlistChangeListener? = null fun setWishlistChangeListener(listener: OnWishlistChangeListener) { this.listener = listener } private fun initAdapter() { val adapter = WishlistAdapter(wishlistIndexes) { targetIndex -> // 触发回调通知Shop Fragment listener?.onWishlistItemUpdated(targetIndex) // 同步更新本地心愿单索引列表 updateWishlistLocalData(targetIndex) } recyclerView.adapter = adapter } private fun updateWishlistLocalData(removeIndex: Int) { // 处理心愿单索引列表的本地更新逻辑... } }Wishlist Adapter中触发回调
class WishlistAdapter( private val wishlistIndexes: List<Int>, private val onItemRemoved: (Int) -> Unit ) : RecyclerView.Adapter<WishlistAdapter.ViewHolder>() { // ... 其他Adapter代码 inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(productIndex: Int) { itemView.btn_remove.setOnClickListener { onItemRemoved(productIndex) } } } }
方案3:EventBus(简化跨组件通信)
如果你的项目已经在用EventBus,这是个快速实现的方案,通过事件发送来完成刷新通知:
定义刷新事件类
data class WishlistRefreshEvent(val productIndex: Int)Shop Fragment注册并接收事件
class ShopFragment : Fragment() { private lateinit var productAdapter: ProductAdapter override fun onStart() { super.onStart() EventBus.getDefault().register(this) } override fun onStop() { super.onStop() EventBus.getDefault().unregister(this) } @Subscribe(threadMode = ThreadMode.MAIN) fun handleWishlistRefresh(event: WishlistRefreshEvent) { productAdapter.notifyItemChanged(event.productIndex) } }Wishlist Adapter中发送事件
itemView.btn_remove.setOnClickListener { EventBus.getDefault().post(WishlistRefreshEvent(productIndex)) // 同步更新心愿单索引列表 }
小提示:
因为你的心愿单存的是全商品的索引,刷新时优先用notifyItemChanged(index)而不是notifyDataSetChanged(),这样能避免RecyclerView全量重绘,提升性能。
内容的提问来源于stack exchange,提问作者Toufic Batache

