Skip to content
Advertisement

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

Hello I’m trying to get Weather information by using OpenWeatherAPI.

So to connect with OpenWeatherAPI I used Retrofit library. (And also my project is using MVVM Pattern)

The problem is that the onResponse() of OpenWeatherRepos is called after the init() of the MainActivityClass is terminated.

So OpenWeather is still getting null instances.

I don’t know much about API call order because it’s my first time on Android. So I’d appreciate it if you could explain it in detail.

Here is my code.

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());
            }
        });
    }

}

And this is my log

        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

Advertisement

Answer

call callWeatherAPI() in first before init().

call init() after onResponse() or insice onResponse() you need to make sure you get the OpenWeather data

Advertisement