如何在两个搭载RecyclerView的Fragment间传递数据并更新购物车列表
问题排查与修复方案
你现有代码存在4个核心错误:
CartRecyclerAdapter数据更新逻辑错误
你的SubmitItem方法中调用Items.toMutableList().add(Item),toMutableList()会生成一个全新的临时集合,添加操作是作用在这个临时对象上的,类内原本的Items集合完全没有被修改,所以getItemCount永远返回0,自然不会渲染任何条目。而且就算修改了数据,也没有调用RecyclerView的刷新通知方法,UI不会同步更新。
- 适配器实例不统一
你在ItemRecyclerAdapter中调用SubmitItem的CartAdapter是你自己新建的实例,和CartFragment中绑定购物车RecyclerView的CartRecyclerAdapter实例完全是两个独立的对象,数据不互通,你加在新实例里的数据永远不会被购物车页面的RecyclerView读取到。
- 适配器实例不统一
- 跨Fragment直接调用逻辑不符合安卓规范
两个Fragment之间默认不能直接通信,直接持有对方适配器的引用容易引发内存泄漏、空指针等问题,官方推荐通过共享ViewModel或者宿主Activity做中转。
- 跨Fragment直接调用逻辑不符合安卓规范
- ViewHolder引用错误
你的CartRecyclerAdapter中onCreateViewHolder返回的是ItemRecyclerAdapter.ItemViewHolder,但你自己已经定义了CartRecyclerAdapter专属的ItemViewHolder,两个ViewHolder绑定的布局不一样,就算有数据也会显示异常甚至崩溃。
- ViewHolder引用错误
修复步骤
步骤1:修复CartRecyclerAdapter的逻辑
class CartRecyclerAdapter : RecyclerView.Adapter<CartRecyclerAdapter.ItemViewHolder>() { // 改用MutableList支持数据修改 private val items = mutableListOf<ItemPost>() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { // 返回自己的ViewHolder,不要用商品列表的 return ItemViewHolder( LayoutInflater.from(parent.context) .inflate(R.layout.layout_item_cart_list, parent, false) ) } override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { holder.bind(items[position]) } override fun getItemCount(): Int = items.size fun submitItem(item: ItemPost) { items.add(item) // 通知RecyclerView插入了新条目,刷新UI notifyItemInserted(items.size - 1) } // 新增批量更新数据的方法,后面配合ViewModel用 fun submitList(newList: List<ItemPost>) { items.clear() items.addAll(newList) notifyDataSetChanged() } class ItemViewHolder constructor(itemView: View): RecyclerView.ViewHolder(itemView) { val itemImage: ImageView = itemView.Item_image_cart val itemTitle: TextView = itemView.Item_title_cart val itemCategory: TextView = itemView.Item_category_cart val itemPrice: TextView = itemView.Item_price_cart fun bind(itemPost: ItemPost) { itemTitle.text = itemPost.Itemtitle itemCategory.text = itemPost.ItemCategory itemPrice.text = itemPost.ItemPrice val requestOptions = RequestOptions() .placeholder(R.drawable.ic_baseline_brush_24) .error(R.drawable.ic_baseline_brush_24) Glide.with(itemView.context) .applyDefaultRequestOptions(requestOptions) .load(itemPost.image) .into(itemImage) } } }
步骤2:创建共享ViewModel存储购物车数据
新建CartViewModel.kt,和宿主Activity绑定,两个Fragment都可以访问同一个实例:
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.example.karawapplication.models.ItemPost class CartViewModel : ViewModel() { // 用LiveData存放购物车列表,支持数据变化监听 val cartItemList = MutableLiveData<MutableList<ItemPost>>(mutableListOf()) fun addItemToCart(item: ItemPost) { val currentList = cartItemList.value ?: mutableListOf() currentList.add(item) cartItemList.postValue(currentList) } }
步骤3:修改商品列表侧的添加逻辑
首先修改ItemRecyclerAdapter,把点击事件回调到Shop Fragment,不要直接操作Cart的适配器:
// 在ItemRecyclerAdapter类内加个点击回调接口 var onItemAddClick: ((ItemPost) -> Unit)? = null // 原来的点击事件改成回调 ItemButton.setOnClickListener { Toast.makeText(itemView.context, "${itempost.image}, ${itempost.Itemtitle}, ${itempost.ItemPrice}", Toast.LENGTH_SHORT).show() onItemAddClick?.invoke(itempost) }
然后在Shop Fragment中初始化适配器的时候设置回调,获取ViewModel实例调用添加方法:
import androidx.fragment.app.activityViewModels class Shop : Fragment(){ // 获取和Activity绑定的CartViewModel实例,和Cart Fragment拿到的是同一个 private val cartViewModel: CartViewModel by activityViewModels() private lateinit var itemAdapter : ItemRecyclerAdapter // ... 保留其他原有代码 ... private fun initRecyclerView() { ShopRecycleView.layoutManager = LinearLayoutManager(activity) itemAdapter = ItemRecyclerAdapter() // 设置添加商品的点击回调 itemAdapter.onItemAddClick = { item -> cartViewModel.addItemToCart(item) Toast.makeText(context, "已添加到购物车", Toast.LENGTH_SHORT).show() } ShopRecycleView.adapter = itemAdapter } }
如果你的项目没有引入
lifecycle-livedata-ktx和lifecycle-viewmodel-ktx依赖,把by activityViewModels()换成下面的写法即可:private val cartViewModel by lazy { ViewModelProvider(requireActivity())[CartViewModel::class.java] }
步骤4:修改Cart Fragment,监听购物车数据变化更新UI
import androidx.fragment.app.activityViewModels class Cart : Fragment() { private val cartViewModel: CartViewModel by activityViewModels() private lateinit var cartAdapter: CartRecyclerAdapter // ... 保留其他原有代码 ... private fun initRecyclerView() { Cart_RecyclerView.layoutManager = LinearLayoutManager(activity) cartAdapter = CartRecyclerAdapter() Cart_RecyclerView.adapter = cartAdapter // 监听购物车列表变化,自动更新适配器数据 cartViewModel.cartItemList.observe(viewLifecycleOwner) { cartList -> cartAdapter.submitList(cartList) } } }
内容的提问来源于stack exchange,提问作者Apprent1ce
相关产品推荐
相关产品推荐

