I am fetching a list of products from an api using retrofit and displaying it in an activity using recycler view. Now when I click on a specific item it should open its details page where there are more details about the product. It’s working fine for first 15 items but after that I get this error in my logcat and in the app it just throws me to the first screen which contains a button(view products).
Here is the code of activity containing recycler view:
@AndroidEntryPoint
class ProductListActivity: AppCompatActivity() {
private lateinit var binding: ProductlistRecyclerviewBinding
private val productViewModel: ProductListActivityViewModel by viewModels()
private lateinit var productAdapter: ProductAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ProductlistRecyclerviewBinding.inflate(layoutInflater)
setContentView(binding.root)
initRecyclerView()
getProductsFromInternet()
productViewModel.productList.observe(this){
it.let {
productAdapter.updateProducts(it)
}
}
productViewModel.isLoading.observe(this) {
binding.progressCircular.isVisible = it
}
}
private fun getProductsFromInternet() {
productViewModel.getProducts()
}
private fun initRecyclerView() {
productAdapter = ProductAdapter(arrayListOf())
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = productAdapter
}
}
Here is it’s viewModel:
@HiltViewModel
class ProductListActivityViewModel @Inject constructor(
private val getProductUseCase: GetProductUseCase
): ViewModel() {
val productList = MutableLiveData<ArrayList<Product>>()
val isLoading = MutableLiveData<Boolean>()
fun getProducts(){
isLoading.postValue(true)
viewModelScope.launch {
val products = getProductUseCase.invoke()
Log.d("ProductListActivity", "Fetched products: $products")
if (products != null){
productList.postValue(products)
isLoading.postValue(false)
}
}
}
}
Here is its adapter:
class ProductAdapter(private val productList: ArrayList<Product>): RecyclerView.Adapter<ProductViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return ProductViewHolder(layoutInflater.inflate(R.layout.productlist_item,parent,false))
}
override fun getItemCount(): Int {
return productList.size
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val currentProduct = productList[position]
holder.render(currentProduct, holder.itemView.context)
holder.itemView.setOnClickListener {
goToProduct(
currentProduct, holder.itemView.context
)
}
}
private fun goToProduct(product: Product, context: Context) {
val intent = Intent(context, ProductDetailsActivity::class.java)
intent.putExtra("product",product)
context.startActivity(intent)
}
fun updateProducts(newProducts: ArrayList<Product>) {
productList.clear()
productList.addAll(newProducts)
notifyDataSetChanged()
}
}
and it’s viewHolder:
class ProductViewHolder(view: View): RecyclerView.ViewHolder(view) {
private val binding = ProductlistItemBinding.bind(view)
fun render(product: Product, context: Context) {
Glide.with(context).load(product.thumbnail).into(binding.imageView)
binding.idTextView.text = "Product ${product.id}"
binding.titleTextView.text = "${product.title}"
}
}
This is the code of details screen where I am receiving the particular product:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProductDetailsBinding.inflate(layoutInflater)
setContentView(binding.root)
val product = intent.getParcelableExtra<Product>("product")