Android Kotlin:从BasketDialogFragment向BasketFragment的RecyclerView添加条目
解决方案:通过共享ViewModel实现跨Fragment购物篮数据同步
1. 创建共享购物篮ViewModel
用ViewModel统一持有购物篮数据,提供添加商品方法和可观察的LiveData,让BasketFragment能实时感知数据变化。
import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class BasketViewModel : ViewModel() { private val _basketItems = MutableLiveData<MutableList<ProductItem>>(mutableListOf()) val basketItems: LiveData<MutableList<ProductItem>> = _basketItems fun addItemToBasket(item: ProductItem) { val currentList = _basketItems.value ?: mutableListOf() // 可在此处添加重复商品的数量累加逻辑 currentList.add(item) _basketItems.postValue(currentList) } }
2. 在宿主Activity中初始化ViewModel
因为两个Fragment都依附于GlassContainerActivity,通过Activity的ViewModelProvider获取实例,确保数据全局共享。
class GlassContainerActivity : AppCompatActivity() { private lateinit var basketViewModel: BasketViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_glass_container) basketViewModel = ViewModelProvider(this)[BasketViewModel::class.java] } }
3. 改造BasketDialogFragment实现添加逻辑
在Dialog中获取共享ViewModel,点击按钮时调用添加方法,传入当前展示的商品条目。
class BasketDialogFragment : DialogFragment() { private val currentItem: ProductItem by lazy { arguments?.getParcelable("PRODUCT_ITEM") ?: ProductItem() } private lateinit var basketViewModel: BasketViewModel override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_basket_dialog, container, false) basketViewModel = ViewModelProvider(requireActivity())[BasketViewModel::class.java] view.addToBasket.setOnClickListener { basketViewModel.addItemToBasket(currentItem) dismiss() } return view } }
4. 改造BasketFragment监听数据更新
观察ViewModel的LiveData,数据变化时自动刷新RecyclerView。
class BasketFragment : Fragment() { private lateinit var basketViewModel: BasketViewModel private lateinit var basketAdapter: BasketAdapter override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_basket, container, false) basketAdapter = BasketAdapter(mutableListOf()) view.recyclerView.apply { adapter = basketAdapter layoutManager = LinearLayoutManager(context) } basketViewModel = ViewModelProvider(requireActivity())[BasketViewModel::class.java] basketViewModel.basketItems.observe(viewLifecycleOwner) { items -> basketAdapter.updateData(items) } return view } }
5. 给BasketAdapter添加数据更新方法
让Adapter能接收新数据源并刷新列表:
class BasketAdapter(private var items: MutableList<ProductItem>) : RecyclerView.Adapter<BasketAdapter.ViewHolder>() { // 省略ViewHolder、onCreateViewHolder、onBindViewHolder等基础代码 fun updateData(newItems: MutableList<ProductItem>) { items.clear() items.addAll(newItems) notifyDataSetChanged() // 追求性能可替换为DiffUtil实现局部刷新 } }
6. 打开Dialog时传递商品数据
在GlassContainerActivity的条目点击事件中,把选中商品通过arguments传入Dialog:
// 条目点击逻辑示例 itemView.setOnClickListener { val selectedItem = adapter.currentList[position] val dialog = BasketDialogFragment() val args = Bundle().apply { putParcelable("PRODUCT_ITEM", selectedItem) } dialog.arguments = args dialog.show(supportFragmentManager, "BasketDialog") }
补充说明
- 采用ViewModel+LiveData的方案,无需手动管理Fragment间的接口回调,自动适配生命周期,避免内存泄漏。
- 若需要处理重复商品的数量累加,可在ViewModel的
addItemToBasket方法中添加逻辑:遍历现有列表,匹配商品ID后更新数量,再提交数据。
内容的提问来源于stack exchange,提问作者Gangsta
相关产品推荐
相关产品推荐

