I am trying to display recyclerview list data using adapter. So far there is no error and I think my code logic is correct, but it didn't show the list when I run the app.
Below is my MainActivity code
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
setSupportActionBar(activityMainBinding.mainToolbar)
binding = activityMainBinding.contentMain
val rv = binding.recyclerView
val clickListener = { view: View, bandName:String ->
//Deal with click feature later, show the list first
}
adapter = RVAdapter(clickListener)
rv.adapter = adapter
rv.layoutManager = LinearLayoutManager(this)
adapter.submitlist(bandResources.values.toMutableList())
Below is my RVAdapter code
class RVAdapter(private val clickListener: (view:View, bandName: String)->Unit)
: ListAdapter<BandInfo,RVAdapter.ViewHolder>(Diff())
{
inner class ViewHolder(val bandRowBinding : BandRowBinding)
: RecyclerView.ViewHolder(bandRowBinding.root) {
init {
bandRowBinding.root.setOnClickListener{
//Deal with click feature later, show the list first
}
}
}
private var bands = mutableListOf<BandInfo>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val bandRowBinding = BandRowBinding.inflate(LayoutInflater.from(parent.context),
parent, false)
return ViewHolder(bandRowBinding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.bandRowBinding
bands[position].let{
binding.bandTitle.text = it.name
binding.bandCreated.text = it.time
}
}
fun submitlist(items: MutableList<BandInfo>){
bands = items
}
Where did I go wrong?
CodePudding user response:
When using ListAdapter
, you don't need to store the Band list in adapter.
And you don't need to declare another submitlist
function because ListAdapter already had it, just simply call submitList()
function from ListAdapter
itself.
CodePudding user response:
Your RecyclerView Adapter is implementing a ListAdapter
which already handles the internal list and its submitList
method for you.
By adding the bands
list inside the adapter and adding your submitList
method you are not using what is provided by the ListAdapter
and hence your RecyclerView will show you nothing as the internal state of the adapter will always have an empty list.
Remove bands
from the adapter and your submitList method. If you want to access the internal list of your adapter you can use currentList
as a replacement of bands
.
CodePudding user response:
You've added a submitlist
method to ListAdapter
, whereas ListAdapter
has its own submitList
method.
I think my code logic is correct, but it didn't show the list
Your submitlist
is assigning a new list to bands
, but you're never notifying the adapter about it. You can call notifyDataSetChanged()
after assigning list to bands
, It would start showing your list in the recyclerview.
fun submitlist(items: MutableList<BandInfo>){
bands = items
notifyDataSetChanged()
}
Using
notifyDataSetChanged()
is not efficient
notifyDataSetChanged()
doesn't tell the reyclerView
what data is changed, and it forces to recreate the whole list, that is not efficient. We should always use specific notify methods like notifyItemChanged
, notifyItemInserted
and notifyItemRemoved
. So, recyclerView
have to draw only the required changes.
ListAdapter
has its own submitList
method which takes a new list and uses provided diff
implementation to display it in the recyclerView
. It takes care of notifying process and only calls the required methods by comparing the old and new list using the provided diff
implementation.
You've to make a few changes for in your RVAdapter
for your adapter
to work.
class RVAdapter(private val clickListener: (view:View, bandName: String)->Unit)
: ListAdapter<BandInfo, RVAdapter.ViewHolder>(Diff())
{
inner class ViewHolder(val bandRowBinding : BandRowBinding)
: RecyclerView.ViewHolder(bandRowBinding.root) {
init {
bandRowBinding.root.setOnClickListener{
//Deal with click feature later, show the list first
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val bandRowBinding = BandRowBinding.inflate(LayoutInflater.from(parent.context),
parent, false)
return ViewHolder(bandRowBinding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.bandRowBinding
getItem(position).let{ //use `getItem` method of ListAdapter to get current item
binding.bandTitle.text = it.name
binding.bandCreated.text = it.time
}
}
}