【问题标题】:How to get total items from Paging 3 Android using Kotlin to implement onclicklistener for each item?如何使用 Kotlin 从 Paging 3 Android 获取总项目以实现每个项目的 onclicklistener?
【发布时间】:2021-04-13 00:29:42
【问题描述】:

我正在关注这篇文章here。 一切运行良好,但现在我想为每个项目实现 onclicklistener。

这是我的代码:

SongViewModelAdapter.kt

    class SongViewModelAdapter(private val onSelect: ((ViewModelLyric?) -> Unit)?) : PagingDataAdapter<ViewModelLyric,
        SongViewModelAdapter.SongViewHolder>(Companion) {

    val TAG = "SongViewModelAdapter"

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val dataBinding = LyricDataBinding.inflate(
            layoutInflater,
            parent,
            false
        )
        return SongViewHolder(dataBinding)
    }

    override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
        val lyric = getItem(position) ?: return
        holder.bindLyric(lyric, onSelect)
    }

    companion object : DiffUtil.ItemCallback<ViewModelLyric>() {
        override fun areItemsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
            return oldItem == newItem
        }
    }

    inner class SongViewHolder(
        private val dataBinding: LyricDataBinding
    ) : RecyclerView.ViewHolder(dataBinding.root) {
        fun bindLyric(lyric: ViewModelLyric, onSelect: ((ViewModelLyric?) -> Unit)?) {
            dataBinding.itemTitle.text = lyric.title
            dataBinding.itemArtist.text = lyric.artist

            dataBinding.root.setOnClickListener {
                onSelect?.let { it1 -> it1(lyric) }
            }
        }
    }
}

HomeFragment.kt

    @AndroidEntryPoint
class HomeFragment : Fragment() {

    val TAG = "HomeFragment"

    private lateinit var binding : FragmentHomeBinding
    private val viewModel by viewModels<HomeFragmentViewModel>()
    private var adapter = SongViewModelAdapter(null)

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(
            inflater, R.layout.fragment_home, container, false)
        binding.productsRecyclerView.adapter = SongViewModelAdapter(::onSelect)
        return binding.root
    }

    private fun onSelect(viewModelLyric: ViewModelLyric?) {
            val id = viewModelLyric?.id

            val bundle = bundleOf("id" to id)

            Log.d(TAG, id.toString())
            view?.findNavController()?.navigate(R.id.songDetailFragment, bundle)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setLyricsAdapter()
        getLyrics()
        setProgressBarAccordingToLoadState()
    }

    private fun setLyricsAdapter() {
        binding.productsRecyclerView.adapter = adapter
    }

    private fun getLyrics() {
        lifecycleScope.launch {
            viewModel.flow.collectLatest {
                adapter.submitData(it)
            }
        }
    }

    private fun setProgressBarAccordingToLoadState() {
        lifecycleScope.launch {
            adapter.loadStateFlow.collectLatest {
                binding.progressBar.isVisible = it.append is LoadState.Loading
            }
        }
    }
}

我目前正在使用 FirestorePagingAdapter,它运行良好。对于那些在第 3 页有经验的人,您将如何传递总项目以实现每个项目的点击侦听器。看到类似的问题,但从来没有一个明确的解决方案。挠了一天的头。非常感谢您的帮助。

编辑 1:添加 HomeFragment.kt

编辑 2:根据用户建议进行了更新。点击还是不行。我需要添加空检查。

【问题讨论】:

    标签: android kotlin google-cloud-firestore android-paging-3


    【解决方案1】:

    在适配器内部处理点击不是一个好习惯。

    适配器关注点只是充当我们数据的桥梁,而不是处理点击的 recyclerview。将其传递回片段/活动可以恢复它。其次,使用回调可能会导致内存泄漏,因为它会引用片段/活动。

    class YourRecyclerViewAdapter(private val onSelect: (ViewModelLyric?) -> Unit) : PagingDataAdapter<ViewModelLyric, SongViewModelAdapter.SongViewHolder>(Companion) {
    
        override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
            val lyric = getItem(position) ?: return
            holder.bindLyric(lyric)
        }
    
        class SongViewHolder(private val binding: YourViewBinding) : RecyclerView.ViewHolder(dataBinding.root) {
    
            fun bindLyric(yourDataType: ViewModelLyric?, onSelect: (ViewModelLyric?) -> Unit) {
               dataBinding.itemTitle.text = lyric.title
               dataBinding.itemArtist.text = lyric.artist
               dataBinding.root.setOnClickListener {
                   onSelect(yourDataType)
               }
            }
        }
    }
    

    在您的片段/活动中

    // Set this adapter to your recycler view
    binding.productsRecyclerView.adapter = YourRecyclerViewAdapter { viewModelLyric-> 
        // Handle click here
    }
    

    编辑:

    SongViewModelAdapter

    class SongViewModelAdapter(private val onSelect: (ViewModelLyric) -> Unit) : PagingDataAdapter<ViewModelLyric, SongViewModelAdapter.SongViewHolder>(Companion) {
        
        val TAG = "SongViewModelAdapter"
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            val dataBinding = LyricDataBinding.inflate(layoutInflater, parent, false)
            return SongViewHolder(dataBinding)
        }
    
        override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
            val lyric = getItem(position) ?: return
            holder.bindLyric(lyric, onSelect)
        }
    
        companion object : DiffUtil.ItemCallback<ViewModelLyric>() {
            
            override fun areItemsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
                return oldItem.id == newItem.id
            }
    
            override fun areContentsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
                return oldItem == newItem
            }
        }
    
        class SongViewHolder(private val dataBinding: LyricDataBinding) : RecyclerView.ViewHolder(dataBinding.root) {
            
            fun bindLyric(lyric: ViewModelLyric, onSelect: (ViewModelLyric) -> Unit)) {
                dataBinding.itemTitle.text = lyric.title
                dataBinding.itemArtist.text = lyric.artist
                dataBinding.root.setOnClickListener {
                    onSelect(lyric)
                }
            }
        }
    }
    

    HomeFragment

    @AndroidEntryPoint
    class HomeFragment : Fragment() {
    
        val TAG = "HomeFragment"
    
        private lateinit var binding : FragmentHomeBinding
        private val viewModel by viewModels<HomeFragmentViewModel>()
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
            binding.productsRecyclerView.adapter = SongViewModelAdapter(::onSelect)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            getLyrics()
            setProgressBarAccordingToLoadState()
        }
    
        private fun onSelect(lyric: ViewModelLyric) {
            // handle click here
        }
    
        private fun getLyrics() {
            lifecycleScope.launch {
                viewModel.flow.collectLatest {
                    binding.adapter.submitData(it)
                }
            }
        }
    
        private fun setProgressBarAccordingToLoadState() {
            lifecycleScope.launch {
                adapter.loadStateFlow.collectLatest {
                    binding.progressBar.isVisible = it.append is LoadState.Loading
                }
            }
        }
    }
    

    【讨论】:

    • 我会尝试您的建议并回复您。感谢您抽出时间来回答。
    • @thesamoanppprogrammer 评论说我们的部分看起来不错。也看看我的回答。
    • @thesamoanppprogrammer 我会这样做。检查更新。
    • @thesamoanppprogrammer 你想在哪里访问它?使用binding.adapter 访问它?
    • @thesamoanppprogrammer 检查更新的答案。
    猜你喜欢
    • 1970-01-01
    • 2020-11-17
    • 2021-10-02
    • 1970-01-01
    • 2020-11-20
    • 2019-07-20
    • 1970-01-01
    相关资源
    最近更新 更多