带有 ListAdapter 的 RecyclerView

Posted

技术标签:

【中文标题】带有 ListAdapter 的 RecyclerView【英文标题】:RecyclerView with ListAdapter 【发布时间】:2020-09-14 12:45:53 【问题描述】:

我正在尝试将我的适配器转换为 ListAdapter,以便将来包含分页库。 我的应用程序是一个基本的 2 片段注释应用程序,第一个片段具有回收器视图,第二个片段具有 EditText 以将文本插入回收器视图。 我已经实现了一切,由于某种原因,在调用 submitList() 后,我的 recyclerview 没有显示任何内容。 我用我的适配器列表观察我的 livedata 列表,我的 livedata 列表正在从房间数据库中获取数据,我将数据查询到其中。在我将我的适配器转换为 ListAdapter 之前一切正常

有什么建议吗?

我的适配器类:

package com.example.mvvm_example

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.mvvm_example.db.Word

interface OnItemClickListener : View.OnClickListener 
    override fun onClick(v: View?) 
    


class ListAdapterCallBack : DiffUtil.ItemCallback<Word>() 
    override fun areItemsTheSame(oldItem: Word, newItem: Word): Boolean 
        return oldItem.mWord == newItem.mWord
    

    override fun areContentsTheSame(oldItem: Word, newItem: Word): Boolean 
        return oldItem == newItem
    


class WordAdapter(
    private val context: Context,
    private val onItemClickListener: OnItemClickListener
) :
    ListAdapter<Word, WordAdapter.WordViewHolder>(ListAdapterCallBack()) 
    private var wordList = listOf<Word>()

    class WordViewHolder(private val view: View) : RecyclerView.ViewHolder(view) 
        private val textView = view.findViewById<TextView>(R.id.textView)!!

        fun onBind(listener: OnItemClickListener, word: Word) 
            textView.text = word.getmWord()
            view.setOnClickListener 
                listener.onClick(view)
            
        
    

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder 
        val inflater = LayoutInflater.from(context)
        return WordViewHolder(inflater.inflate(R.layout.recyclerview_item, parent, false))
    

    override fun getItemCount(): Int 
        return wordList.size
    

    fun setWords(list: MutableList<Word>) 
        wordList = list
        notifyDataSetChanged()
    

    override fun submitList(list: MutableList<Word>?) 
        Log.d("Adapter", "list sumbitted list is $list.toString()")
        super.submitList(list?.let  ArrayList(it) )
    

    override fun onBindViewHolder(holder: WordViewHolder, position: Int) 
        val word = wordList[position]
        holder.onBind(onItemClickListener, word)

    

我的第一个包含 recyclerview 的片段:

package com.example.mvvm_example

import android.app.Activity
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.mvvm_example.db.Word
import kotlinx.android.synthetic.main.fragment_first.*

private const val TAG = "firstFrag"

class FirstFragment : Fragment() 
    private lateinit var viewModel: AppViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? 
        // Inflate the layout for this fragment
        Log.d(TAG, "onCreateView called")
        return inflater.inflate(R.layout.fragment_first, container, false)
    

    override fun onActivityCreated(savedInstanceState: Bundle?) 
        Log.d(TAG, "onActivityCreated called")
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(AppViewModel::class.java)

        val recyclerView = requireActivity().findViewById<RecyclerView>(R.id.recyclerview)
        val adapter =
            WordAdapter(requireActivity().applicationContext, object : OnItemClickListener 
                override fun onClick(v: View?) 
                    super.onClick(v)
                    Toast.makeText(
                        requireActivity().applicationContext,
                        "item clicked",
                        Toast.LENGTH_SHORT
                    ).show()
                
            )

        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(requireContext())
        viewModel.getAllWords().observe(requireActivity(), Observer 
            adapter.submitList(it)
        )
        fab.setOnClickListener 
            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
        

        delfab.setOnClickListener 
            viewModel.deleteAllWords()
            Toast.makeText(requireContext(), "Words Deleted", Toast.LENGTH_LONG).show()
        

    

我的 Word 数据类:

package com.example.mvvm_example.db

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import org.jetbrains.annotations.NotNull


@Entity(tableName = "word_table")
data class Word(

    @ColumnInfo(name = "word")
    @PrimaryKey
    @NotNull
     val mWord: String
) 


    fun getmWord() = mWord

编辑 如果我用adapter.setWords(it) 切换adapter.submitList(it) 它也可以工作.. 所以它必须是submitList() 方法有问题

【问题讨论】:

【参考方案1】:

如果您使用ListAdapter,则意味着它自己管理列表项。您应该删除您的 wordList 内部和方法 getItemCount。对于访问数据,仅调用getItem(position) 方法。无需覆盖方法submitList

【讨论】:

我爱你!为我解决了。我正在查看地球上的所有线程,但没有一个能解决我的问题.. 我想这应该很明显

以上是关于带有 ListAdapter 的 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

带有DiffUtil的RecyclerView(ListAdapter)阻止UI线程

将图像 url 设置为 listadapter 以使用 Picasso 显示图像

将图片网址设置为listadapter以使用Picasso显示图片

使用 ListAdapter 将项目添加到 ListView

ListAdapter 未更新 RecyclerView 中的项目

在 Fragment 中设置一个新的 ListAdapter