有效房间和装修模式

时间:2019-03-08 22:52:31

标签: android retrofit android-room

正如你们中的一些人可能遇到的那样,即使在使用google文档之后,我也面临着与Getting Initial Value for LiveData Always Returning NullLiveData.getValue() returns null with Room相同的问题。

许多人似乎都有自己的实现方式,如何异步加载本地数据,在一段时间后到期并请求新数据,先加载本地数据并稍后刷新等等。

(API请求之前或之后),主要的问题始终是如何对新本地数据的加载或替换作出反应,我已经看到一些解决方案将AsyncTaskObservable.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;
        }
    }
}

这有效吗?我的意思是,这不是反模式。 我已经测试过了,到目前为止一切都很好。
在片段,方向,锁定屏幕等之间进行切换时,我没有在所有者和上下文中检测到任何可能的泄漏或空引用。

这有效吗?即使是这样,我应该避免什么并且应该改进什么。

我遗漏了ViewModelDao,因为它们大多数都非常相似且清晰。

0 个答案:

没有答案