Search code examples
kotlinarraylistindexingandroid-activityandroid-adapter

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 occuring in my Activity's Adapter


When I started the MainActivity, my app crashed and returns the error : java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 on my stack trace. Here's my adapter code:

class MainAdapter: PagingDataAdapter<ListStoryItem, MainAdapter.MyViewHolder>(DIFF_CALLBACK) {

    private val listStories = ArrayList<ListStoryItem>()
    private lateinit var onItemClickCallback: OnItemClickCallback

    class MyViewHolder(var binding: StoryItemBinding) : RecyclerView.ViewHolder(binding.root) {

    }

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

    override fun getItemCount(): Int {
        return listStories.size
    }

    @SuppressLint("NotifyDataSetChanged")
    fun setListStories(stories: List<ListStoryItem>) {
        listStories.clear()
        listStories.addAll(stories)
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            val (photoUrl, createdAt, name, description, _) = listStories[position]
            holder.binding.tvName.text = name
            holder.binding.tvStory.text = description
            val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
            val outputFormat = SimpleDateFormat("MMM dd, yyyy - hh:mm a", Locale.getDefault())
            val date = inputFormat.parse(createdAt)
            val formattedDateTimeString = outputFormat.format(date)

            holder.binding.tvDate.text = formattedDateTimeString
            Glide.with(holder.itemView.context)
                .load(photoUrl)
                .into(holder.binding.imageView2)
            holder.binding.imageView2.setOnClickListener{
                onItemClickCallback.onItemClicked(listStories[holder.adapterPosition])
        }
    }

    fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback) {
        this.onItemClickCallback = onItemClickCallback
    }

    interface OnItemClickCallback {
        fun onItemClicked(data: ListStoryItem)
    }

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<ListStoryItem>() {
            override fun areItemsTheSame(oldItem: ListStoryItem, newItem: ListStoryItem): Boolean {
                return oldItem == newItem
            }

            override fun areContentsTheSame(oldItem: ListStoryItem, newItem: ListStoryItem): Boolean {
                return oldItem.id == newItem.id
            }
        }
    }
}

The stacktrace leads to the onBindViewHolder() part of the val (photoUrl, createdAt, name, description, _) = listStories[position]. I'm guessing my setListStories() function causing the list to be empty. But I couldn't find out why the error occurred. This is the stacktrace : Stacktrace


Solution

  • When using PagingAdapter, best way to update is to use adapter.submitData() with PageData<T> instead of List and to read the item in onBindViewHolder you should use getItem(position) rather than using your local List as data holder! Refer here PagingDataAdapter