Как некоторые из вас, возможно, сталкивались, я столкнулся с той же проблемой, что и Получение начального значения для LiveData, всегда возвращающей ноль , а LiveData.getValue () возвращает ноль с Room даже послеgoogle docs.
Многие люди, похоже, имеют собственную реализацию того, как асинхронно загружать локальные данные, через какое-то время истекает срок их действия и запрашивать новые данные, сначала загружать локальные данные и обновлять позже и т. д.on.
Основная проблема всегда заключается в том, как реагировать на загрузку или замену новых локальных данных (до или после запросов API), и я видел некоторые решения, смешивающие AsyncTask
, Observable.mergeDelayError
и даже некоторые флаги, чтобы избежать состояния гонки.
Я прочитал из предыдущих ссылок, что было бы хорошо применить Observer
к загрузке локальных данных вместо асинхронной задачи, что будет означать, чтов хранилище есть ссылка на 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
, поскольку большинство из них очень похожи и понятны.