Reputation: 88
On recyclerview I'm setting a list, using MVVM where I'm getting an error, IndexOutOfBoundsException. code I use for recyclerview adapter is below - onBindViewHolder is where I set articles:List
class MainAdapter(private val context: Context,private val articles:List<Article>) : ListAdapter<Article, MainAdapter.MainViewHolder>(DiffUtil()) {
inner class MainViewHolder(val binding: HomeRecViewBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder {
val binding = HomeRecViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MainViewHolder(binding)
}
override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
val articles_ = articles[position]
holder.binding.artical = articles_
}
class DiffUtil : androidx.recyclerview.widget.DiffUtil.ItemCallback<Article>() {
override fun areItemsTheSame(oldItem: Article, newItem: Article): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Article, newItem: Article): Boolean {
return oldItem == newItem
}
}
}
my ViewModel is given below
val article : LiveData<NewsModel>
get() = repoHelper.article
my main Activity
class TestActivity : AppCompatActivity() {
lateinit var binding: ActivityTestBinding
lateinit var mainViewModel: MainViewModel
lateinit var article_: List<Article>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this,R.layout.activity_test)
article_ = ArrayList()
val mainAdapter = MainAdapter(this,article_)
binding.recView.apply {
this.layoutManager = LinearLayoutManager(this@TestActivity)
this.adapter = mainAdapter
}
val apiHelper = RetrofitHelper.getInstance().create(ApiHelper::class.java)
val database_ = DBHelper.getDatabase(applicationContext)
val repoHelper = RepoHelper(apiHelper,database_,applicationContext)
mainViewModel = ViewModelProvider(this,ViewModelFactory(repoHelper)).get(MainViewModel::class.java)
mainViewModel.article.observe(this, Observer {
Log.d("list_of_article",it.articles.toString())
mainAdapter.submitList(it.articles)
})
}
what's the main cause for this error and how do I resolve it.
Upvotes: 0
Views: 327
Reputation: 23357
article_ = ArrayList()
val mainAdapter = MainAdapter(this,article_)
Here you provide an empty list to the Adapter.
After this never changes!
mainAdapter.submitList(it.articles)
does not set this list in the adapter.
So val articles_ = articles[position]
will try to access something from an empty list.
As a matter of fact. You don't even need to have this list at all. ListAdapter has methods to access the list you provide with submitList
Instead of
val articles_ = articles[position]
you can do
val articles_ = getItem(position)
and then you can remove the articles completely there so change
class MainAdapter(private val context: Context,private val articles:List<Article>)
to
class MainAdapter(private val context: Context)
and change
val mainAdapter = MainAdapter(this,article_)
to
val mainAdapter = MainAdapter(this)
Upvotes: 1
Reputation: 1718
You are not implementing the getItemCount()
. It returns the size of the list.
override fun getItemCount(): Int {
return articles.size
}
Cause of IndexOutOfBoundsException
is that you are trying to access the index of list which is beyond the size of list.
The size of list is 2. So the elements will be at index 0 and 1. If you try to access index 2 then you will get to see IndexOutOfBoundsException
Upvotes: 0