I am trying to show data in nested recyclerview like play store after fetching data from the server.I have successfully retrieved and parse title of parent recyclerview but unable to show horizontal recyclerview which is a child layout.
I am getting error in CategortAdapter.kt at the time of viewmodel instantiation it is showing red line under ViewModelProvider(context) in below line:
val viewModel = ViewModelProvider(context).get(CatImagesViewModel::class.java)
Below is my JSON response:
{
"status": "200",
"message": "Success",
"result": [
{
"_id": "60f516fa846e059e2f19c50c",
"category": "Shirts",
"sku": [
{
"name": "Oxford shirt",
"brand": "John players",
"price": "25",
"color": "Blue",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/shi1.jpg?alt=media&token=64779194-e3b5-484f-a610-c9a20648b64c"
},
{
"name": "Buttoned down",
"brand": "Gap originals",
"price": "45",
"color": "Pink",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/shi2.jpg?alt=media&token=0b207b90-f1bc-4771-b877-809648e6bdc1"
},
{
"name": "Collared",
"brand": "Arrow",
"price": "30",
"color": "White",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/shi3.jpg?alt=media&token=2c1bb3f8-e739-4f09-acbc-aa11fed795e3"
},
{
"name": "Printed",
"brand": "John players",
"price": "30",
"color": "Olive green",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/shi4.jpg?alt=media&token=666f94bf-4769-44fe-a909-3c81ca9262f7"
},
{
"name": "Hoodie",
"brand": "Levis",
"price": "44",
"color": "Yellow",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/shi5.jpg?alt=media&token=65fccef4-a882-4278-b5df-f00eb2785bf1"
}
]
},
{
"_id": "60f51c37846e059e2f19c50f",
"category": "Shoes",
"sku": [
{
"name": "Sneakers",
"brand": "Puma",
"price": "35",
"color": "Black and white",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/sho1.jpg?alt=media&token=d078988d-9e85-4313-bb4a-c9d46e09f0b9"
},
{
"name": "Running shoe",
"brand": "Nike",
"price": "99",
"color": "Multicolor",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/sho2.jpg?alt=media&token=ed2e7387-3cf6-44df-9f7d-69843eb0bcdf"
},
{
"name": "Yezzy",
"brand": "Adidas",
"price": "349",
"color": "Gray",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/sho3.jpg?alt=media&token=2c37ef76-37bb-4bdd-b36c-dea32857291f"
},
{
"name": "Sneakers",
"brand": "Puma",
"price": "79",
"color": "Black",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/sho4.jpg?alt=media&token=4acd763e-8b93-47cd-ba45-92f34af4cf83"
},
{
"name": "Joyride running",
"brand": "Nike",
"price": "80",
"color": "White",
"img": "https://firebasestorage.googleapis.com/v0/b/koovs-1ff31.appspot.com/o/sho5.jpg?alt=media&token=e3780dcc-52cb-49d5-9791-e0a44870716c"
}
]
}
]
}
In the parent recycler view which is vertical I want to show title category as shown in JSON response and sku in horizontal recycler view.
In child recycler view I want to show images only which comes under sku array.
Below is my code:
ApiService.kt
interface ApiService {
@GET("getProducts")
suspend fun getCategories(): Response<Product>
@GET("getProducts")
suspend fun getCatImg(): Response<Product>
}
Product.kt
data class Product(
val message: String,
val result: List<Result>,
val status: String
)
Result.kt
data class Result(
val _id: String,
val category: String,
val sku: List<Sku>
)
Sku.kt
data class Sku(
val brand: String,
val color: String,
val img: String,
val name: String,
val price: String
)
parent_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/catTitle"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="#345"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/childRecycler"
android:layout_below="@+id/catTitle"
android:layout_marginTop="8dp"/>
</RelativeLayout>
child_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
app:cardCornerRadius="3dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/img"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
In below adapter I am fetching category title and child recycler view as i have successfully retrieved titles but unable to parse recyclerview:
CategoryAdapter.kt
class CategoryAdapter(private val context: Context,private val categories:List<Result>): RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return
ViewHolder(ParentRowBinding.inflate(LayoutInflater.from(parent.context),parent,false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val model = categories[position]
holder.binding.catTitle.text = model.category
holder.binding.childRecycler.setHasFixedSize(true)
holder.binding.childRecycler.layoutManager = LinearLayoutManager(context)
val viewModel = ViewModelProvider(context).get(CatImagesViewModel::class.java)
}
override fun getItemCount(): Int {
return categories.size
}
class ViewHolder(val binding:ParentRowBinding): RecyclerView.ViewHolder(binding.root)
}
CatImagesViewModel.kt
class CatImagesViewModel: ViewModel() {
private var catImageList:MutableLiveData<List<List<Sku>>> = MutableLiveData()
fun getCatImg(): LiveData<List<List<Sku>>>{
viewModelScope.launch(Dispatchers.IO) {
val retrofit = RetrofitClient.getRetrofitClient().create(ApiService::class.java)
val response = retrofit.getCatImg()
if(response.isSuccessful){
val skus: MutableList<List<Sku>> = mutableListOf()
val cnt = response.body()!!.result.size
for(i in 0 until cnt){
skus.add(response.body()!!.result[i].sku)
}
catImageList.postValue(skus)
}
}
return catImageList
}
}
Below is the adapter for parsing images in child recycler view which is horizontal one:
CatImgAdapter.kt
class CatImgAdapter(private val context: Context,private val imgList:List<Sku>): RecyclerView.Adapter<CatImgAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(ChildRowBinding.inflate(LayoutInflater.from(parent.context),parent,false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val model = imgList[position]
Glide.with(context).load(model.img).into(holder.binding.img)
}
override fun getItemCount(): Int {
return imgList.size
}
data class ViewHolder(val binding:ChildRowBinding): RecyclerView.ViewHolder(binding.root)
}
Below is the ViewModel for fetching category title vor vertical recycler view:
CategoriesViewModel.kt
class CategoriesViewModel: ViewModel() {
private var categoryList: MutableLiveData<List<Result>> = MutableLiveData()
fun getAllCategory(): LiveData<List<Result>> {
viewModelScope.launch(Dispatchers.IO) {
val retrofit = RetrofitClient.getRetrofitClient().create(ApiService::class.java)
val response = retrofit.getCategories()
if (response.isSuccessful) {
categoryList.postValue(response.body()!!.result)
}
}
return categoryList
}
}
Someone let me know what I am doing wrong or the best way to achieve the desired layout.
