如何根据模型类型使用同一Adapter跳转至两个不同Fragment
解决RecyclerView不同条目类型跳转对应Fragment的问题
核心问题分析
当前FavoriteListAdapter的点击回调仅支持WordsWithMeanings类型,无法传递Proverb类型数据,导致无法触发对应Fragment的跳转。我们需要修改回调的参数类型,并在Fragment中根据条目类型分支处理跳转逻辑。
步骤1:修改FavoriteListAdapter的点击回调
将Adapter构造函数中的回调参数改为支持接收任意类型,同时为Proverb条目添加点击事件触发回调:
private const val WORD_VIEW_TYPE = 0 private const val PROVERB_VIEW_TYPE = 1 class FavoriteListAdapter( private val viewModel: WordViewModel, private val onItemClicked: (Any) -> Unit // 修改回调参数类型为Any ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { val mData = mutableListOf<Any>() // ... 其他原有代码不变 override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val element = mData[position] when (getItemViewType(position)) { WORD_VIEW_TYPE -> { holder.itemView.setOnClickListener { onItemClicked(element as WordsWithMeanings) } (holder as WordItemViewHolder).bind(element as WordsWithMeanings, viewModel) } PROVERB_VIEW_TYPE -> { // 新增Proverb条目的点击事件 holder.itemView.setOnClickListener { onItemClicked(element as Proverb) } (holder as ProverbItemViewHolder).bind(element as Proverb, viewModel) } } } // ... 其他原有代码不变 }
步骤2:在FavoriteFragment中处理不同类型的跳转
初始化Adapter时,在回调中判断点击条目的具体类型,分别触发对应Fragment的导航动作(需确保导航图中已定义actionFavouriteFragmentToProverbDetailFragment):
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) adapter = FavoriteListAdapter(viewModel) { item -> when(item) { is WordsWithMeanings -> { val action = FavoriteFragmentDirections.actionFavouriteFragmentToWordDetailFragment(item) findNavController().navigate(action) } is Proverb -> { val action = FavoriteFragmentDirections.actionFavouriteFragmentToProverbDetailFragment(item) findNavController().navigate(action) } } } // ... 其他原有代码不变 }
可选优化:用密封类提升类型安全性
如果想避免Any类型带来的强制转换风险,可以定义密封类统一条目类型,让代码更健壮:
1. 定义密封类
sealed class FavoriteItem { data class WordEntry(val data: WordsWithMeanings) : FavoriteItem() data class ProverbEntry(val data: Proverb) : FavoriteItem() }
2. 修改Adapter的数据源和回调
class FavoriteListAdapter( private val viewModel: WordViewModel, private val onItemClicked: (FavoriteItem) -> Unit // 改为密封类类型 ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { val mData = mutableListOf<FavoriteItem>() // 数据源改为密封类列表 override fun getItemViewType(position: Int): Int { return when (mData[position]) { is FavoriteItem.WordEntry -> WORD_VIEW_TYPE is FavoriteItem.ProverbEntry -> PROVERB_VIEW_TYPE } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val element = mData[position] when (element) { is FavoriteItem.WordEntry -> { holder.itemView.setOnClickListener { onItemClicked(element) } (holder as WordItemViewHolder).bind(element.data, viewModel) } is FavoriteItem.ProverbEntry -> { holder.itemView.setOnClickListener { onItemClicked(element) } (holder as ProverbItemViewHolder).bind(element.data, viewModel) } } } // ... 其他原有代码不变 }
3. 修改Fragment中添加数据的逻辑
viewModel.allWordsWithMeanings.observe(this.viewLifecycleOwner) { items -> items.forEach { if (it.word.isFavorite == true) { adapter.mData.add(FavoriteItem.WordEntry(it)) } } favoriteFragmentFavoriteStatus() } viewModel.allProverbs.observe(this.viewLifecycleOwner) { items -> items.forEach { if (it.isFavorite == true) { adapter.mData.add(FavoriteItem.ProverbEntry(it)) } } }
4. 修改Fragment中的跳转逻辑
adapter = FavoriteListAdapter(viewModel) { item -> when(item) { is FavoriteItem.WordEntry -> { val action = FavoriteFragmentDirections.actionFavouriteFragmentToWordDetailFragment(item.data) findNavController().navigate(action) } is FavoriteItem.ProverbEntry -> { val action = FavoriteFragmentDirections.actionFavouriteFragmentToProverbDetailFragment(item.data) findNavController().navigate(action) } } }
内容的提问来源于stack exchange,提问作者oguzata
相关产品推荐
相关产品推荐

