簡體   English   中英

如何根據 model 的類型使用相同的適配器導航到 2 個不同的片段?

[英]How to navigate to 2 different fragments using same adapter according to the type of model?

我的問題圖

我想根據我的 model 的類型使用相同的適配器導航 2 個不同的片段。但我的問題是我無法使用兩種不同的模型處理 onItemClicked。 如你看到的:

    private val onItemClicked: (WordsWithMeanings) -> Unit

最喜歡的片段

class FavoriteFragment : Fragment(R.layout.fragment_favorite) {

    private var _binding: FragmentFavoriteBinding? = null
 
    private val binding get() = _binding!!

    private val viewModel: WordViewModel by activityViewModels {
        WordViewModelFactory(
            (activity?.application as WordApplication).database.wordDao()
        )
    }

    private lateinit var adapter: FavoriteListAdapter
 
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentFavoriteBinding.inflate(inflater)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapter = FavoriteListAdapter(viewModel) {
            val action =          FavoriteFragmentDirections.actionFavouriteFragmentToWordDetailFragment(it). 
            this.findNavController().navigate(action)
        }

        binding.recyclerView.adapter = adapter

        viewModel.allWordsWithMeanings.observe(this.viewLifecycleOwner) { items ->
            items.let {
                for (i in items) {
                    if (i.word.isFavorite == true) {
                        adapter.mData.add(i)
                    }
                }
            }
            favoriteFragmentFavoriteStatus()
        }

        viewModel.allProverbs.observe(this.viewLifecycleOwner) { items ->
            items.let {
                for (i in items) {
                    if (i.isFavorite == true) {
                        adapter.mData.add(i)
                    }
                }
            }
        }

        binding.recyclerView.layoutManager = LinearLayoutManager(this.context)
    }
}`
```

收藏列表適配器

private const val WORD_VIEW_TYPE = 0
private const val PROVERB_VIEW_TYPE = 1

class FavoriteListAdapter(
    private val viewModel: WordViewModel,
    private val onItemClicked: (WordsWithMeanings) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    val mData = mutableListOf<Any>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            WORD_VIEW_TYPE -> WordItemViewHolder(
                FavoriteItemsBinding.inflate(
                    inflater,
                    parent,
                    false
                )
            )
            PROVERB_VIEW_TYPE -> ProverbItemViewHolder(
                FavoriteItemsBinding.inflate(
                    inflater,
                    parent,
                    false
                )
            )
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    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 -> {
                (holder as ProverbItemViewHolder).bind(element as Proverb, viewModel)
            }
        }
    }

    class WordItemViewHolder(private var binding: FavoriteItemsBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(favoriteWordsWithMeanings: WordsWithMeanings, viewModel: WordViewModel) {
            binding.apply {
                title.text = favoriteWordsWithMeanings.word.word
                content.text = favoriteWordsWithMeanings.means[0].wordMean
                favoriteButton.isChecked =
                    favoriteWordsWithMeanings.word.isFavorite == true
                favoriteButton.setOnClickListener {
                    if (favoriteButton.isChecked) {
                        favoriteButton.isChecked = true
                        viewModel.updateFavoriteWord(favoriteWordsWithMeanings, true)
                    } else {
                        favoriteButton.isChecked = false
                        viewModel.updateFavoriteWord(favoriteWordsWithMeanings, false)
                    }
                }
            }
        }
    }

    class ProverbItemViewHolder(private var binding: FavoriteItemsBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(favoriteProverb: Proverb, viewModel: WordViewModel) {
            binding.apply {
                title.text = favoriteProverb.proverb
                content.text = favoriteProverb.proverbMean
                favoriteButton.isChecked =
                    favoriteProverb.isFavorite == true
                favoriteButton.setOnClickListener {
                    if (favoriteButton.isChecked) {
                        favoriteButton.isChecked = true
                        viewModel.updateFavoriteProverb(favoriteProverb, true)
                    } else {
                        favoriteButton.isChecked = false
                        viewModel.updateFavoriteProverb(favoriteProverb, false)
                    }
                }
            }
        }
    }

    override fun getItemCount(): Int {
        return mData.size
    }

    override fun getItemViewType(position: Int): Int {
        return when (mData[position]) {
            is WordsWithMeanings -> WORD_VIEW_TYPE
            is Proverb -> PROVERB_VIEW_TYPE
            else -> throw IllegalArgumentException("Unsupported type")
        }
    }
}

所以我只導航到一個片段。 我想要做的是,如果單擊的項目是“WordsWithMeanings”,則導航到 WordDetailFragment,如果單擊的項目是“Proverb”,則導航到 ProverbDetailFragment。 有沒有正確的方法來做到這一點?

解決方案:

首先我改變了這個

private val onItemClicked: (WordsWithMeanings) -> Unit

對此

private val onItemClicked: (Any) -> Unit

之后使用這樣的操作解決了我的問題。

       action = if (it is WordsWithMeanings) {
            FavoriteFragmentDirections.actionFavouriteFragmentToWordDetailFragment(it)
        } else {
            FavoriteFragmentDirections.actionFavouriteFragmentToProverbDetailFragment(it as Proverb)
        }
        this.findNavController().navigate(action as NavDirections)

您正在適配器 onItemClicked 回調中傳遞一個WordsWithMeaning項目。 您可以檢查傳遞給回調的項目是WordsWithMeaning類型還是Proverb類型,然后采取相應措施:

adapter = FavoriteListAdapter(viewModel) {
    val action = if (it is Proverb) {
        // navigate to proverb details
    } else {
        // navigate to word details
    }       
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM