正如你们中的一些人可能遇到的那样,即使在使用google文档之后,我也面临着与Getting Initial Value for LiveData Always Returning Null和LiveData.getValue() returns null with Room相同的问题。
许多人似乎都有自己的实现方式,如何异步加载本地数据,在一段时间后到期并请求新数据,先加载本地数据并稍后刷新等等。
(API请求之前或之后),主要的问题始终是如何对新本地数据的加载或替换作出反应,我已经看到一些解决方案将AsyncTask
,Observable.mergeDelayError
混合在一起,甚至有些标志,以避免出现竞争情况。
我从前面的链接中读到,最好将Observer
应用于本地数据负载而不是asynctask,这将意味着存储库引用了实例化的LifecycleOwner
他,所以我想出了解决方法。
public class DataRepository {
public static final String TAG = "DATA_REPO";
private DataApi DataApi;
private DataDao DataDao;
private LifecycleOwner owner;
public MutableLiveData<List<Data>> allData;
public MutableLiveData<Data> singleData;
public DataRepository(Application application, LifecycleOwner owner) {
MyAppRoomDatabase db = MyAppRoomDatabase.getDatabase(application);
DataDao = db.DataDao();
DataApi = MyApp.getRetrofitSingleton().create(DataApi.class);
this.owner = owner;
allData = new MutableLiveData<>();
}
public LiveData<List<Data>> getAllData() {
final Call<List<Data>> callToApi = DataApi.getAllData();
callToApi.enqueue(new Callback<List<Data>>() {
@Override
public void onResponse(Call<List<Data>> call, Response<List<Data>> response) {
if(response.isSuccessful()){
List<Data> responseData;
responseData = response.body();
insertAll(responseData);
allData.setValue(responseData);
} else {
Log.e(TAG, "Error in response:"+response.toString());
// This is my workaround
getAll().observe(owner, new Observer<List<Data>>() {
@Override
public void onChanged(@Nullable List<Data> data) {
allData.setValue(data);
}
});
}
}
@Override
public void onFailure(Call<List<Data>> call, Throwable t) {
Log.e(TAG, "Error in network:" + t.toString());
// This is my workaround
getAll().observe(owner, new Observer<List<Data>>() {
@Override
public void onChanged(@Nullable List<Data> data) {
Log.i(TAG, "categorias:" + data);
allData.setValue(data);
}
});;
}
});
return allData;
}
public void insertOne (Data Data) {
new insertAsyncTask(DataDao).execute(Data);
}
public void insertAll (List<Data> Data) {
new insertAllAsyncTask(DataDao).execute(Data);
}
public LiveData<List<Data>> getAll () {
return DataDao.getAllData();
}
private static class insertAsyncTask extends AsyncTask<Data, Void, Void> {
private DataDao mAsyncTaskDao;
insertAsyncTask(DataDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Data... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}
private static class insertAllAsyncTask extends AsyncTask<List<Data>, Void, Void> {
private DataDao mAsyncTaskDao;
insertAllAsyncTask(DataDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final List<Data>... params) {
List<Data> data = params[0];
for (Data Data: data){
mAsyncTaskDao.insert(Data);
Log.i(TAG, "inserted:" + data);
}
return null;
}
}
}
这有效吗?我的意思是,这不是反模式。
我已经测试过了,到目前为止一切都很好。
在片段,方向,锁定屏幕等之间进行切换时,我没有在所有者和上下文中检测到任何可能的泄漏或空引用。
这有效吗?即使是这样,我应该避免什么并且应该改进什么。
我遗漏了ViewModel
和Dao
,因为它们大多数都非常相似且清晰。