You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView无法展示JSON响应但ViewModel可正常获取数据求助

问题1:Retrofit接口返回类型定义与实际JSON结构不匹配

你提供的接口返回JSON根节点是单个对象,包含products数组字段,但你的Retrofit方法定义返回值为Call<List<MobileProducts>>,期望根节点是数组,类型不匹配导致Gson解析虽然不会崩溃但拿到的是空数据。
修改RetrofitService代码:

interface RetrofitService {
    @GET("/nancymadan/assignment/db")
    // 把返回类型从 List<MobileProducts> 改为 MobileProducts
    fun getAllMovies() : Call<MobileProducts>

    companion object {
        var retrofitService: RetrofitService? = null
        fun getInstance() : RetrofitService {
            if (retrofitService == null) {
                val retrofit = Retrofit.Builder()
                    .baseUrl("https://my-json-server.typicode.com")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                retrofitService = retrofit.create(RetrofitService::class.java)
            }
            return retrofitService!!
        }
    }
}

问题2:ViewModel数据类型、赋值逻辑错误

当前ViewModel的LiveData存储的是List<MobileProducts>,但实际你需要传递给Adapter渲染的是Product列表,需要调整类型和赋值逻辑:

class MainViewModel constructor(private val repository: MainRepository)  : ViewModel() {
    // 修改LiveData泛型为List<Product>
    val movieList = MutableLiveData<List<Product>>()
    val errorMessage = MutableLiveData<String>()

    fun getAllMovies() {
        val response = repository.getAllMovies()
        // 回调的泛型同步改为MobileProducts
        response.enqueue(object : Callback<MobileProducts> {
            override fun onResponse(call: Call<MobileProducts>, response: Response<MobileProducts>) {
                // 取返回对象里的products字段赋值
                movieList.postValue(response.body()?.products ?: emptyList())
            }

            override fun onFailure(call: Call<MobileProducts>, t: Throwable) {
                errorMessage.postValue(t.message)
            }
        })
    }
}

同时要同步修改MainRepository里getAllMovies方法的返回类型为Call<MobileProducts>。

问题3:RecyclerView未设置布局管理器

RecyclerView必须设置LayoutManager才会渲染条目,你当前只设置了Adapter,缺少布局管理器配置,在MainActivity的onCreate里添加:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    // 新增这行,设置线性布局管理器,可根据需求切换为GridLayoutManager等
    binding.recyclerview.layoutManager = LinearLayoutManager(this)
    binding.recyclerview.adapter = adapter

    // 其余原有逻辑不变
    viewModel = ViewModelProvider(this, MyViewModelFactory(MainRepository(retrofitService))).get(MainViewModel::class.java)
    viewModel.movieList.observe(this, Observer {
        Log.d(TAG, "onCreate: $it")
        adapter.setMovieList(it)
    })
    viewModel.errorMessage.observe(this, Observer { })
    viewModel.getAllMovies()
}

问题4:Adapter更新数据后未通知刷新

确认你的MainAdapter的setMovieList方法内,给内部列表赋值后,调用了notifyDataSetChanged()或者增量刷新方法,示例:

class MainAdapter : RecyclerView.Adapter<MainAdapter.MyViewHolder>() {
    private var movieList: List<Product> = emptyList()

    fun setMovieList(list: List<Product>) {
        this.movieList = list
        // 必须调用通知刷新
        notifyDataSetChanged()
    }

    // 其余Adapter原有逻辑不变
}

其他注意事项

你提供的JSON示例末尾有多余逗号,实际接口返回时请确保JSON格式合法,避免解析异常。

内容的提问来源于stack exchange,提问作者New Bee Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 02:57:03