如何在recyclerview中加载数据?

How to load data in recyclerview?

我正在创建一个 Android 应用程序并尝试在 Recyclerview 中设置数据,我在 kotlin 中使用 MVVM 架构模式,我可以在 logcat 中看到数据但是当应用程序加载时我没有在我的 recyclerview 中查看任何数据。以下是我的代码。

主要活动

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()

        })
    }
}

产品适配器

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) {

}

存储库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())
        }
    }
}

视图模型

class ProductViewModel (private val productRepository: ProductRepository ) :ViewModel() {
    init {
        viewModelScope.launch(Dispatchers.IO){
            productRepository.getProducts()
        }
    }

    val products : LiveData<MobileList>
    get() = productRepository.products
}

工厂

class ProductViewModelFactory (private val productRepository: ProductRepository) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return ProductViewModel (productRepository) as T
    }

}

型号

data class MobileList(
    val products: List<Product>
)

data class Product(
    val image_url: String,
    val name: String,
    val price: String,
    val rating: Int
)

JSON 回应

{
  "products": [
    {
      "name": "test",
      "price": "34999",
      "image_url": "url",
      "rating": 4
    },
    {
      "name": "test2",
      "price": "999",
      "image_url": "url",
      "rating": 4
    },]}

首先确保您在 RecyclerView 上设置了 layoutManager

这里的问题是您的 ProductAdapter 从未有过数据。 notifyDataSetChanged 不是通知适配器您 modify/add/update 数据集然后您将调用 notifyDataSetChanged 的魔术棒。这就是它的工作原理。

在您的情况下,您已经 movies 列出了您的适配器,但您从未给它分配任何东西,它总是空的。 有几种方法。只是让它工作你可以有一个方法在你的适配器中添加数据然后通知它。

fun addData(data:List<MobileList>){
        movies.addAll(data)
        notifyDataSetChanged()
    }

现在,当您在 change 中获取数据时,您将调用此方法。

productViewModel.products.observe(this,{
       it?.let{ items ->
        adapter.addData(items)
       }
    })

这应该有效。

类型修复更新 - 好像你的类型搞砸了。为什么你的 repo returns 是 MobileList 的对象?当您在 adapter 中使用 MobileList 列表时。您的适配器应容纳 var movies = mutableListOf<Products>().

productViewModel.products.observe(this,{
       it?.let{ item ->
        adapter.addData(item.products)
       }
    })