"Empty list doesn't contain element at index 0" error when implementing Android Recycler View with checkbox

I am implementing a recycler view with it’s items as checkbox. My data is coming from ROOM database and this recycler view is inside a dialog fragment.

Dialog Fragment :

 override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = ScheduleFloorDialogBinding.inflate(layoutInflater)
        createProfileViewModel = CreateProfileViewModel(Application())
        floorProfileDialogAdapter = FloorProfileDialogAdapter()

        binding.rvFloorsForScheduling.layoutManager = LinearLayoutManager(requireActivity())
        binding.rvFloorsForScheduling.adapter = floorProfileDialogAdapter

        return binding.root
    }

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

        val floorList: MutableList<String> = mutableListOf()

        //Getting list of all floors
        createProfileViewModel.totalFloors.observe(viewLifecycleOwner) {
            Timber.d("List of floors received : $it")

            val intList = it.map(String::toInt)
            val maxFloorValue = intList.last()
            var count = 0

            try {
                while (count <= maxFloorValue) {
                    floorList.add(count.toString())
                    count++
                }
            } catch (e: Exception) {
                Timber.d("Exception: $e")
            }
            floorProfileDialogAdapter.getAllFloors(floorList)
            Timber.d("Floor List : $floorList")
        }
    }

I am able to send list of data from here to my adapter.

Adapter:

class FloorProfileDialogAdapter() : RecyclerView.Adapter<FloorProfileDialogAdapter.MyViewHolder>() {

    var floors = emptyList<String>()

    inner class MyViewHolder(val binding: ScheduleFloorDialogItemBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = ScheduleFloorDialogItemBinding.inflate(inflater, parent, false)

        return MyViewHolder(binding)
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentFloor = floors[position]
        Timber.d("Current floor: $currentFloor")
        holder.binding.floorCheckBox.text = "Floor $currentFloor"
    }

    override fun getItemCount(): Int {
        return floors.toString().length
    }

    fun getAllFloors(floorsReceived: List<String>) {
        Timber.d("Floors received : $floorsReceived")
        this.floors = floorsReceived
    }
}

Log inside the Adapter’s getAllFloor method shows that list has been received:

  • enter image description here

But inside onBindViewHolder() when I use the position I get the error saying :

java.lang.IndexOutOfBoundsException: Empty list doesn't contain element at index 0.

>Solution :

The view is already inflated when you initialized the floorProfileDialogAdapter with an empty list, it won’t be changed till you use notifyDataSetChange()
it’s a solution which is not recommended

or
Using ListAdapter from Androidx Recycler view Package: it has its own submit list so every time you submit a list it notifies data set change and it compares it with the previous one

Check documentation

Leave a Reply