RxJava订阅返回Null对象:接口列表Size显示Null问题排查
我来帮你梳理下这个问题的核心原因,以及对应的解决办法:
1. 字段序列化不匹配(最直接的原因)
服务器返回的JSON里,列表字段是大写的Items,但你的数据模型DistrictItems里定义的是小写的items:
服务器返回JSON片段:
{"Items": [ ... ]}
数据模型:data class DistrictItems( var items: List<TaxDistrictModel>? )
默认情况下,序列化框架(比如Gson、Moshi)会严格按照字段名的大小写来映射,所以框架找不到对应的items字段,就会把它设为null,这就是日志里it.items?.size输出null的直接原因。
解决办法:
给DistrictItems的items字段加上序列化注解,指定对应JSON里的字段名。比如用Gson的话:
import com.google.gson.annotations.SerializedName data class DistrictItems( @SerializedName("Items") // 对应JSON里的大写Items var items: List<TaxDistrictModel>? )
如果用的是其他序列化框架(比如Moshi),用对应的注解即可,比如@Json(name = "Items")。
2. 异步操作的同步返回错误(隐藏的逻辑问题)
你的getRegions()方法试图直接返回districtModelTypeTitles,但RxJava的订阅是异步执行的:
fun getRegions(): DistrictItems? { showLoading() api.getDistricts() .subscribeOnMain(...) // 这里是异步线程执行,不会阻塞当前方法 return districtModelTypeTitles // 这行代码会在订阅回调执行前就执行,所以返回的是初始值(大概率是null) }
也就是说,当你调用getRegions()时,方法会立刻返回,而此时onNext回调还没执行,districtModelTypeTitles还没被赋值,所以返回的肯定是null。
解决办法:
不要试图同步返回异步操作的结果,改用回调、LiveData或者Flow来传递结果。比如用回调的方式:
// 定义回调接口 interface DistrictCallback { fun onSuccess(data: DistrictItems) fun onError(error: Throwable) } fun getRegions(callback: DistrictCallback) { showLoading() api.getDistricts() .subscribeOnMain( onNext = { hideLoading() Log.d("qwerty", "$$$$$$$$ ${it.items?.size}") callback.onSuccess(it) }, onError = { hideLoading() showAlert(it) callback.onError(it) } ) .disposedBy(compositeDisposable) } // 调用的时候 getRegions(object : DistrictCallback { override fun onSuccess(data: DistrictItems) { districtModelTypeTitles = data // 在这里处理数据,比如更新UI } override fun onError(error: Throwable) { // 处理错误 } })
或者用LiveData(适合Android场景):
val districtLiveData = MutableLiveData<DistrictItems>() fun getRegions() { showLoading() api.getDistricts() .subscribeOnMain( onNext = { hideLoading() districtLiveData.value = it }, onError = { hideLoading() showAlert(it) } ) .disposedBy(compositeDisposable) } // 观察LiveData districtLiveData.observe(this) { data -> districtModelTypeTitles = data // 处理数据 }
总结
先解决字段序列化的大小写问题,这是日志显示size为null的直接原因;然后修正异步操作的结果传递方式,避免同步返回未赋值的变量。这样应该就能解决你的问题了。
内容的提问来源于stack exchange,提问作者Akylbek

