Home > Software engineering >  Why submitlist didn't show the list when run the app? [Kotlin]
Why submitlist didn't show the list when run the app? [Kotlin]

Time:10-01

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
        }
    }        
}
  • Related