为什么 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 数据
您好,我正在尝试使用 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 数据