为什么 Retrofit onResponse() 最后被调用,我该如何解决?

Why does Retrofit onResponse() is called at last and how can i fix it?

您好,我正在尝试使用 OpenWeatherAPI 获取天气信息。

所以为了连接 OpenWeatherAPI 我使用了 Retrofit 库。 (而且我的项目正在使用 MVVM 模式)

问题是OpenWeatherRepos的onResponse()是在MainActivityClass的init()结束后调用的

所以 OpenWeather 仍在获取空实例。

我对 API 调用顺序了解不多,因为这是我第一次使用 Android。 如果您能详细解释一下,我将不胜感激。

这是我的代码。

MainActivity.java

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(); //this is called first in code
        Log.i(TAG,"API Connection finish"); //But this is called first
        OpenWeather opw = mavm.getWeather().getValue();
        Log.i(TAG,opw.toString());
    }
}

MainActivityViewModel.java

public class MainActivityViewModel extends ViewModel {

    private final String TAG = "MainActivityViewModel";

    private MutableLiveData<OpenWeather> weather;
    private OpenWeatherRepos opwRepo;

    public void init(){
        if(weather != null){
            return;
        }
        opwRepo = OpenWeatherRepos.getInStance();
        weather = opwRepo.getWeather();
        Log.i(TAG,"API Connection finish");
    }

    public LiveData<OpenWeather> getWeather(){
        return weather;
    }
}

OpenWeatherRepos.java

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;
    private OpenWeather opw;

    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>();
        opw = new OpenWeather();
        callWeatherAPI();
        Log.i(TAG,opw.toString());
        data.setValue(opw);
        return data;
    }

    private void callWeatherAPI() {

        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) {
                opw = response.body();
                Log.i(TAG,"API CONNECT SUCCESS");
            }

            @Override
            public void onFailure(Call<OpenWeather> call, Throwable t) {
                Log.d(TAG,"onFailure : "+t.getMessage());
            }
        });
    }

}

这是我的日志

        08/27 04:20:17: Launching 'app' on Nexus 5X API 28.
        $ adb shell am start -n "wook.co.weather/wook.co.weather.view.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
        Connected to process 12910 on device 'emulator-5554'.
        Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
        I/wook.co.weathe: Not late-enabling -Xcheck:jni (already on)
        W/wook.co.weathe: Unexpected CPU variant for X86 using defaults: x86
        W/wook.co.weathe: Accessing hidden method Landroid/graphics/drawable/Drawable;->getOpticalInsets()Landroid/graphics/Insets; (light greylist, linking)
            Accessing hidden field Landroid/graphics/Insets;->left:I (light greylist, linking)
            Accessing hidden field Landroid/graphics/Insets;->right:I (light greylist, linking)
            Accessing hidden field Landroid/graphics/Insets;->top:I (light greylist, linking)
            Accessing hidden field Landroid/graphics/Insets;->bottom:I (light greylist, linking)
        W/wook.co.weathe: Accessing hidden field Landroid/view/WindowInsets;->CONSUMED:Landroid/view/WindowInsets; (light greylist, reflection)
        W/wook.co.weathe: Accessing hidden method Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate; (light greylist, linking)
        W/wook.co.weathe: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
        W/wook.co.weathe: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
        W/wook.co.weathe: Accessing hidden method Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V (light greylist, reflection)
        D/NetworkSecurityConfig: No Network Security Config specified, using platform default
        W/wook.co.weathe: Accessing hidden method Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V (light greylist, reflection)
            Accessing hidden method Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V (light greylist, reflection)
            Accessing hidden method Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B (light greylist, reflection)
            Accessing hidden method Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V (light greylist, reflection)
        W/wook.co.weathe: Accessing hidden method Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; (light greylist, reflection)
            Accessing hidden method Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V (light greylist, reflection)
            Accessing hidden method Ldalvik/system/CloseGuard;->warnIfOpen()V (light greylist, reflection)

//////////////////onResponse is not called at here/////////////////////
        I/OpenWeatherRepository: OpenWeather{coord=null, weather=null, base='null', main=null, wind=null, clouds=null, rain=null, snow=null, sys=null, visibility=0, dt=0, timezone=0, id=0, name='null', cod=0}
        I/MainActivityViewModel: API Connection finish
        I/MainActivity: API Connection finish
            OpenWeather{coord=null, weather=null, base='null', main=null, wind=null, clouds=null, rain=null, snow=null, sys=null, visibility=0, dt=0, timezone=0, id=0, name='null', cod=0}
        D/OpenGLRenderer: Skia GL Pipeline
        W/wook.co.weathe: Accessing hidden method Landroid/graphics/Insets;->of(IIII)Landroid/graphics/Insets; (light greylist, linking)
        D/HostConnection: HostConnection::get() New Host Connection established 0xe28a13c0, tid 12938
        D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_async_frame_commands ANDROID_EMU_gles_max_version_3_0 
        I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
        I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
        I/OpenGLRenderer: Initialized EGL, version 1.4
        D/OpenGLRenderer: Swap behavior 1
        W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
        D/OpenGLRenderer: Swap behavior 0
        D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 0 0
        D/EGL_emulation: eglCreateContext: 0xe2885360: maj 3 min 0 rcv 3
        D/EGL_emulation: eglMakeCurrent: 0xe2885360: ver 3 0 (tinfo 0xe28836a0)
        D/HostConnection: createUnique: call
        D/HostConnection: HostConnection::get() New Host Connection established 0xe28a1690, tid 12938
        D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_async_frame_commands ANDROID_EMU_gles_max_version_3_0 
        E/eglCodecCommon: GoldfishAddressSpaceHostMemoryAllocator: ioctl_ping failed for device_type=5, ret=-1
        D/EGL_emulation: eglMakeCurrent: 0xe2885360: ver 3 0 (tinfo 0xe28836a0)
        D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 3 2

    /////////But onResponse are called at here///////////
        I/OpenWeatherRepository: API CONNECT SUCCESS

在 init() 之前先调用 callWeatherAPI()。

在 onResponse() 或 insice onResponse() 之后调用 init() 您需要确保获得 OpenWeather 数据