为什么我在 android 中放入 MutableLiveData 后得到 Null
Why do I get Null after I put into MutableLiveData in android
我尝试使用 OpenWeatherAPI 获取天气信息。
所以我使用了 Retrofit 库。
API连接成功。
但问题是我从 OpenWeather 获得的天气数据API
我将数据放入 MutableLiveData 后突然变为 null。
这是代码
package wook.co.weather.models.repository;
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import wook.co.weather.interfaces.OpenWeatherAPI;
import wook.co.weather.models.dto.OpenWeather;
import wook.co.weather.models.retrofit.RetrofitService;
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 MutableLiveData<OpenWeather> data;
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);
data = new MutableLiveData<OpenWeather>();
callWeatherAPI();
Log.i(TAG,data.getValue().toString()); //error occurs here
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) {
OpenWeather temp = response.body();
Log.i(TAG,"API CONNECT SUCCESS");
if(temp != null){
Log.i(TAG,temp.toString());
data.setValue(temp);
}
}
@Override
public void onFailure(Call<OpenWeather> call, Throwable t) {
Log.d(TAG,"onFailure : "+t.getMessage());
}
});
}
}
这是这段代码的结果
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: wook.co.weather, PID: 10063
java.lang.RuntimeException: Unable to start activity ComponentInfo{wook.co.weather/wook.co.weather.view.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String wook.co.weather.models.dto.OpenWeather.toString()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String wook.co.weather.models.dto.OpenWeather.toString()' on a null object reference
at wook.co.weather.models.repository.OpenWeatherRepos.getWeather(OpenWeatherRepos.java:46)
at wook.co.weather.viewmodels.MainActivityViewModel.init(MainActivityViewModel.java:25)
at wook.co.weather.view.MainActivity.onCreate(MainActivity.java:26)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process: Sending signal. PID: 10063 SIG: 9
我该如何解决这个问题??
我认为问题出在这里:
if(temp != null){
Log.i(TAG,temp.toString());
data.postValue(temp);
Log.i(TAG,data.getValue().toString());
}
postValue()
方法不会立即更新LiveData的值;相反,它将一个任务发布到主线程,最终将更新该值。此处的文档:https://developer.android.com/reference/androidx/lifecycle/MutableLiveData#postValue(T)
这意味着调用 postValue()
然后立即调用 getValue()
将使您收到“旧”值(从您发布新值之前),因为任务不会已完成并更新了 LiveData 的值。
在您的情况下,解决方法是简单地删除第二个 Log.i()
调用。您 可以 修改它来工作,像这样:
data.postValue(temp);
OpenWeather value = data.getValue();
if (value != null) {
Log.i(TAG, value.toString());
}
但这确实没有任何好处;您已经知道 data.getValue()
此时将过时。
我尝试使用 OpenWeatherAPI 获取天气信息。
所以我使用了 Retrofit 库。
API连接成功。
但问题是我从 OpenWeather 获得的天气数据API 我将数据放入 MutableLiveData 后突然变为 null。
这是代码
package wook.co.weather.models.repository;
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import wook.co.weather.interfaces.OpenWeatherAPI;
import wook.co.weather.models.dto.OpenWeather;
import wook.co.weather.models.retrofit.RetrofitService;
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 MutableLiveData<OpenWeather> data;
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);
data = new MutableLiveData<OpenWeather>();
callWeatherAPI();
Log.i(TAG,data.getValue().toString()); //error occurs here
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) {
OpenWeather temp = response.body();
Log.i(TAG,"API CONNECT SUCCESS");
if(temp != null){
Log.i(TAG,temp.toString());
data.setValue(temp);
}
}
@Override
public void onFailure(Call<OpenWeather> call, Throwable t) {
Log.d(TAG,"onFailure : "+t.getMessage());
}
});
}
}
这是这段代码的结果
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: wook.co.weather, PID: 10063
java.lang.RuntimeException: Unable to start activity ComponentInfo{wook.co.weather/wook.co.weather.view.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String wook.co.weather.models.dto.OpenWeather.toString()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String wook.co.weather.models.dto.OpenWeather.toString()' on a null object reference
at wook.co.weather.models.repository.OpenWeatherRepos.getWeather(OpenWeatherRepos.java:46)
at wook.co.weather.viewmodels.MainActivityViewModel.init(MainActivityViewModel.java:25)
at wook.co.weather.view.MainActivity.onCreate(MainActivity.java:26)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process: Sending signal. PID: 10063 SIG: 9
我该如何解决这个问题??
我认为问题出在这里:
if(temp != null){ Log.i(TAG,temp.toString()); data.postValue(temp); Log.i(TAG,data.getValue().toString()); }
postValue()
方法不会立即更新LiveData的值;相反,它将一个任务发布到主线程,最终将更新该值。此处的文档:https://developer.android.com/reference/androidx/lifecycle/MutableLiveData#postValue(T)
这意味着调用 postValue()
然后立即调用 getValue()
将使您收到“旧”值(从您发布新值之前),因为任务不会已完成并更新了 LiveData 的值。
在您的情况下,解决方法是简单地删除第二个 Log.i()
调用。您 可以 修改它来工作,像这样:
data.postValue(temp);
OpenWeather value = data.getValue();
if (value != null) {
Log.i(TAG, value.toString());
}
但这确实没有任何好处;您已经知道 data.getValue()
此时将过时。