Android使用Retrofit获取OpenWeather数据存入MutableLiveData后为空如何解决
根因分析
你遇到的空指针是异步请求时序问题导致的:
- Retrofit的
call.enqueue()是异步网络请求,会在后台线程执行,不会阻塞当前主线程 - 你在调用
callWeatherAPI()之后立刻执行Log.i(TAG,data.getValue().toString()),此时网络请求还没完成,data作为新创建的MutableLiveData还没有被赋值,getValue()返回null,调用toString()就触发了空指针
你在onResponse里能打印出数据,是因为那时候网络请求已经成功返回,才给data完成赋值,代码实际执行顺序和你写代码的顺序不一致。
解决方案
1. 移除/移动即时读取LiveData值的代码
把getWeather方法里的错误日志行删掉,或者移到onResponse里,只有请求成功后再读取data的值:
public MutableLiveData<OpenWeather> getWeather() { retrofit = new RetrofitService().getRetroInstance(BASE_URL); opwAPI = retrofit.create(OpenWeatherAPI.class); data = new MutableLiveData<OpenWeather>(); callWeatherAPI(); // 删除这行错误代码 Log.i(TAG,data.getValue().toString()); return data; } // onResponse里可以正常打印 @Override public void onResponse(Call<OpenWeather> call, Response<OpenWeather> response) { OpenWeather temp = response.body(); Log.i(TAG,"API CONNECT SUCCESS"); if(temp != null){ Log.i(TAG,temp.toString()); data.setValue(temp); // 这里读取data值就不会为空 Log.i(TAG, "请求成功后data值:"+ data.getValue().toString()); } }
2. 遵循LiveData观察者模式使用
不要直接调用data.getValue()来获取值,在ViewModel或Activity层通过observe方法监听LiveData的变化,只有数据更新后才会触发回调,此时数据一定非空:
举个在Activity中观察的示例:
// MainActivity的onCreate里 mainActivityViewModel.getWeatherLiveData().observe(this, openWeather -> { // 这里只有当data赋值成功后才会执行,openWeather非空,直接用就行 Log.i("MainActivity", "获取到天气数据:"+openWeather.toString()); // 更新UI等操作都写在这里 });
3. 可选防护措施
如果有必须直接读取LiveData值的场景,先做空判断,避免空指针:
if(data.getValue() != null){ Log.i(TAG,data.getValue().toString()); }
内容的提问来源于stack exchange,提问作者codingRookie
相关产品推荐
相关产品推荐

