I am creating one Android app and trying to set the data in Recyclerview, I am using MVVM architecture pattern with kotlin, I can see data in logcat but when app loads I am not seeing any data in my recyclerview. Following is my code.
MainActivity
class MainActivity : AppCompatActivity() {
lateinit var productViewModel: ProductViewModel
private lateinit var binding: ActivityMainBinding
val adapter = ProductAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val productService = RetrofitHelper.getInstance().create(ProductService::class.java)
val productRepository = ProductRepository(productService)
productViewModel = ViewModelProvider(this, ProductViewModelFactory(productRepository)).get(ProductViewModel::class.java)
binding.recyclerview.adapter = adapter
productViewModel.products.observe(this,{
Log.d("TEST",it.toString())
adapter.notifyDataSetChanged()
})
}
}
ProductAdapter
class ProductAdapter : RecyclerView.Adapter<ProductViewHolder>() {
var movies = mutableListOf<MobileList>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = AdapterLayoutBinding.inflate(inflater, parent, false)
return ProductViewHolder(binding)
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val movie = movies[position]
holder.binding.name.text = movie.products.get(position).name
Glide.with(holder.itemView.context).load(movie.products.get(position).image_url).into(holder.binding.imageview)
}
override fun getItemCount(): Int {
return movies.size
}
}
class ProductViewHolder(val binding: AdapterLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
}
Repository class
class ProductRepository (private val productService: ProductService) {
private val productLiveData = MutableLiveData<MobileList>()
val products:LiveData<MobileList>
get() = productLiveData
suspend fun getProducts(){
val products = productService.getQuotes()
if(products?.body()!=null)
{
productLiveData.postValue(products.body())
}
}
}
ViewModel
class ProductViewModel (private val productRepository: ProductRepository ) :ViewModel() {
init {
viewModelScope.launch(Dispatchers.IO){
productRepository.getProducts()
}
}
val products : LiveData<MobileList>
get() = productRepository.products
}
Factory
class ProductViewModelFactory (private val productRepository: ProductRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return ProductViewModel (productRepository) as T
}
}
Model
data class MobileList(
val products: List<Product>
)
data class Product(
val image_url: String,
val name: String,
val price: String,
val rating: Int
)
JSON Response
{
"products": [
{
"name": "test",
"price": "34999",
"image_url": "url",
"rating": 4
},
{
"name": "test2",
"price": "999",
"image_url": "url",
"rating": 4
},]}
CodePudding user response:
First of all make sure you have layoutManager
set on the RecyclerView
.
The problem here is Your ProductAdapter
never had the data . notifyDataSetChanged
is not a magic stick to notify the adapter you modify/add/update the dataset and then You will call notifyDataSetChanged
. that's how it works .
In your case You have movies
list your adapter but you never assigned anything to it its always empty .
There are several ways to it. Just to make it work You can have a method to add the data in your adapter and then notify it.
fun addData(data:List<MobileList>){
movies.addAll(data)
notifyDataSetChanged()
}
Now when you get the data inside on change you call this method .
productViewModel.products.observe(this,{
it?.let{ items ->
adapter.addData(items)
}
})
This should work .
Update on type fix - Seems like your type is messed up . Why is your repo returns a object of MobileList
? While you are using a list of MobileList
in adapter . Your adapter should hold var movies = mutableListOf<Products>()
.
productViewModel.products.observe(this,{
it?.let{ item ->
adapter.addData(item.products)
}
})