Android Kotlin中Volley JsonObjectRequest始终触发VolleyError问题
问题根源
报错来自两个核心逻辑错误:
- Volley请求类型不匹配:从你贴的异常信息
Value [{"dbn":"02M260"...}]可以明确看到,接口返回的是JSON数组结构(内容以[开头),但你使用了JsonObjectRequest发起请求——这个请求类默认会把响应解析为单个JSON对象(以{开头的结构),Volley在内部预解析阶段就会抛出JSONException,直接进入错误回调,你写在成功回调里的Gson解析逻辑根本不会执行。 - Gson解析与LiveData使用错误:即使请求成功,你写的解析逻辑也无法正常触发UI更新:一是错误尝试把JSON直接反序列化为
MutableLiveData类型,LiveData是数据容器不是业务数据模型;二是直接把ViewModel中提前初始化的schoolsData变量替换成了Gson生成的新对象,View层注册的观察者是绑定在旧实例上的,永远收不到数据更新。
修复方案
- 将Volley的请求类从
JsonObjectRequest替换为JsonArrayRequest,匹配接口返回的数组结构。 - 修正Gson解析逻辑:通过
TypeToken指定解析类型为List<SchoolsData>,解析完成后调用postValue方法把数据设置到你提前定义好的schoolsDataLiveData实例上,禁止重新给schoolsData变量赋值。 - 额外注意:如果后续遇到数值类型解析错误,可先将
SchoolsData中的total_students、graduation_rate字段类型改为String接收,拿到值后再手动转换为对应数值类型,避免接口返回值类型和本地定义不匹配导致解析失败。
修正后的ViewModel核心代码
class SchoolViewModel: ViewModel() { private val schoolsData = MutableLiveData<List<SchoolsData>>() val _schoolsData: LiveData<List<SchoolsData>> = schoolsData private var satData = MutableLiveData<SATData>() val _satData: LiveData<SATData> = satData private val API_Schools: String = "https://data.cityofnewyork.us/resource/s3k6-pzi2.json" private val API_SAT: String = "https://data.cityofnewyork.us/resource/f9bf-2cp4.json" fun getData(context: Context) { val requestQueue: RequestQueue = Volley.newRequestQueue(context.applicationContext) // 替换为数组请求 val jsonArrayRequest = JsonArrayRequest(Request.Method.GET, API_Schools, null, { response -> try { val gson = Gson() // 处理泛型擦除问题,正确解析为学校列表 val listType = object : TypeToken<List<SchoolsData>>() {}.type val schoolList: List<SchoolsData> = gson.fromJson(response.toString(), listType) // 给原有LiveData实例设置数据,不要重新赋值变量 schoolsData.postValue(schoolList) }catch (e: Exception){ Log.e("PARSE_ERROR", e.stackTraceToString()) } }, { error -> Log.e("REQUEST_ERROR", error.stackTraceToString()) }) requestQueue.add(jsonArrayRequest) } }
替换后重新运行即可正常拿到数据,RecyclerView会自动触发更新。
内容的提问来源于stack exchange,提问作者SirHammouD
相关产品推荐
相关产品推荐

