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

为什么Retrofit的onResponse最后执行?Android MVVM项目该如何修复?

问题原因
  • 你调用的Retrofit enqueue()方法属于异步非阻塞请求:发起请求后直接在当前线程返回,网络请求、响应解析逻辑会在后台子线程执行,直到请求完成才会切回主线程触发onResponse/onFailure回调。主线程的代码执行优先级远高于后台异步回调,所以你在onCreate里主动拿数据时,网络请求还没完成,自然只能拿到初始化的空对象。
  • 你的LiveData没有更新逻辑:你在onResponse里只修改了opw成员变量的指向,没有调用LiveData的setValue()/postValue()方法通知数据更新,就算请求完成,外部观察者也拿不到最新的天气数据。
修复步骤

1. 修改OpenWeatherRepos.java

把需要更新的MutableLiveData传入请求方法,请求完成后主动更新LiveData值:

public class OpenWeatherRepos {
    
    private final String TAG = "OpenWeatherRepository";
    private final static String BASE_URL = "https://api.openweathermap.org/data/2.5/"; 
    private static OpenWeatherRepos instance;
    private Retrofit retrofit;
    private OpenWeatherAPI opwAPI;

    public static OpenWeatherRepos getInStance() {
        if(instance == null){
            instance = new OpenWeatherRepos();
        }
        return instance;
    }

    public MutableLiveData<OpenWeather> getWeather() {
        retrofit = new RetrofitService().getRetroInstance(BASE_URL);
        opwAPI = retrofit.create(OpenWeatherAPI.class);
        MutableLiveData<OpenWeather> data = new MutableLiveData<OpenWeather>();
        // 把LiveData传入请求方法
        callWeatherAPI(data);
        return data;
    }

    private void callWeatherAPI(MutableLiveData<OpenWeather> data) {
        Call<OpenWeather> call = opwAPI.getWeather("seoul","this is my id","kr");
        call.enqueue(new Callback<OpenWeather>() {
            @Override
            public void onResponse(Call<OpenWeather> call, Response<OpenWeather> response) {
                if(response.isSuccessful() && response.body() != null){
                    // 请求成功后更新LiveData,postValue可兼容子线程调用场景
                    data.postValue(response.body());
                    Log.i(TAG,"API CONNECT SUCCESS");
                }
            }

            @Override
            public void onFailure(Call<OpenWeather> call, Throwable t) {
                Log.d(TAG,"onFailure : "+t.getMessage());
                // 失败场景也可以给LiveData传空值或者错误状态,上层做兼容
                data.postValue(null);
            }
        });
    }
}

2. 修改MainActivity.java

不要主动调用getValue()拿数据,改为观察LiveData的更新通知,数据就绪后再做后续操作:

public class MainActivity extends AppCompatActivity {

    private MainActivityViewModel mavm;
    private final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mavm = new ViewModelProvider(this).get(MainActivityViewModel.class);
        mavm.init();
        Log.i(TAG,"开始发起天气请求");
        // 观察LiveData数据更新,数据就绪后自动触发回调
        mavm.getWeather().observe(this, openWeather -> {
            if(openWeather != null){
                Log.i(TAG,"拿到天气数据:" + openWeather.toString());
                // 此处做更新UI等后续操作
            } else {
                Log.e(TAG,"天气请求失败");
            }
        });
    }
}
修复后执行逻辑
  1. Activity onCreate 初始化ViewModel并调用init发起请求,同时注册LiveData观察者
  2. 后台线程执行网络请求,主线程继续执行后续渲染逻辑
  3. 网络请求完成后,Repository更新LiveData的值
  4. LiveData自动通知观察者,Activity回调中拿到最新的天气数据做处理

内容的提问来源于stack exchange,提问作者codingRookie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:15:04