Действительный номер и шаблон дооснащения - PullRequest
0 голосов
/ 09 марта 2019

Как некоторые из вас, возможно, сталкивались, я столкнулся с той же проблемой, что и Получение начального значения для 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, поскольку большинство из них очень похожи и понятны.

...