体系结构组件:即使在onDestroy

时间:2018-09-05 05:44:16

标签: android android-room android-handler android-architecture-components android-livedata

我正在开发一个应用程序,该应用程序需要每30秒进行一次网络通话,并删除先前的数据并插入新的数据。每次插入新数据时,我都会在RecyclerView中显示它。我正在使用Handler进行网络通话,并使用LiveData观察数据更改。一切正常,只是实时数据观察器触发了多次,因此数据被删除并多次插入,从而频繁刷新RecyclerView,从而导致每30秒刷新一次。

下面是我尝试过的代码:

在片段中,我这样做:

private LiveData<List<RestaurantTablesModel>> mData;
private Observer<List<RestaurantTablesModel>> mObserver;
private TablesViewModel mViewModel;

 @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View mView = inflater.inflate(R.layout.fragment_tables, container, false);
    ButterKnife.bind(this, mView);

    TablesViewModelFactory factory = InjectorUtils.provideTablesFactory(getActivity());
    mViewModel = ViewModelProviders.of(this, factory).get(TablesViewModel.class);

    setUpUserRecyclerView();

    return mView;

}

private void setUpRecyclerView() {

  mData = mViewModel.getTablesData(mLocationID);

    mObserver = tablesModels -> {
        if (tablesModels != null) {
            mTablesRecyclerAdapter.addTables(tablesModels);
            Log.e(LOG_TAG, "setUpUserRecyclerView: tablesModels");
        }
    };

  mData.observe(this, mObserver);
}

删除观察者onDestroy:

@Override
public void onDestroy() {
   mData.removeObserver(mObserver);
   super.onDestroy();
}

以下是我在ViewModel中的方法:

public LiveData<List<TablesModel>> getTablesData(int mLocationID){
    return mRepository.getTablesData(mLocationID);
}

存储库:

public LiveData<List<TablesModel>> getTablesData(int mLocationID){

    LiveData<TablesModel[]> mTablesData = mDataSource.getTablesData();

    mTablesData.observeForever(tablesModels -> {
        mExecutors.diskIO().execute(() -> {

            //Completed: delete old table data if there are conflicts.

            if (tablesModels != null) {
                mDatabaseDao.deleteTables();

                mDatabaseDao.insertTablesData(tablesModels);
            }else {
                Log.e(LOG_TAG, "Nothing: ");
            }
        });
        Log.e("Handlers", "repository getTablesData");
    });

    return mDatabaseDao.getTablesData(mLocationID);
}

数据源:

private MutableLiveData<RestaurantTablesModel[]> mDownloadedTablesModel;

public LiveData<RestaurantTablesModel[]> getTablesData() {
    Log.e("Handlers", "getTablesData");
    fetchTablesData();
    return mDownloadedTablesModel;
}

public void fetchTablesData() {

    if (Utils.isNetworkAvailable(mContext)) {
        NetworkUtils.NetworkInterface mInterface = this;

        handler = new Handler();

        runnableCode = new Runnable() {

            @Override
            public void run() {
                // Do something here on the main thread
                Log.e("Handlers", "Called on network thread");

                URL getTablesURL = NetworkUtils.getAllTableUrl(mContext);

                NetworkUtils.getResponseFromAPI(mContext, getTablesURL, mInterface);

                // Repeat this the same runnable code block again another 30 seconds
                // 'this' is referencing the Runnable object
                handler.postDelayed(this, 30000);
            }
        };

        handler.post(runnableCode);

    } else {
        Log.d(LOG_TAG, "fetchTablesData: No network!");
    }
}

现在的问题是,当我的片段被破坏并重新创建时,Observer被触发了多次,以下是日志:

09-05 10:28:29.853 3666-3666/? E/TablesFragment: setUpRecyclerView: tablesModels
09-05 10:28:30.039 3666-3666/? E/TablesFragment: setUpRecyclerView: tablesModels
09-05 10:28:30.607 3666-3666/? E/TablesFragment: setUpRecyclerView: tablesModels
09-05 10:28:30.657 3666-3666/? E/TablesFragment: setUpRecyclerView: tablesModels
09-05 10:28:30.669 3666-3666/? E/TablesFragment: setUpRecyclerView: tablesModels
09-05 10:28:30.704 3666-3666/? E/TablesFragment: setUpRecyclerView: tablesModels

每次重新创建片段时,它触发的次数都比以前多,我认为观察者在片段的重新生成上被调用,并且观察者的先前实例仍在播放中。

但是,如果我要删除OnDestroy中的观察者,为什么会发生呢? 任何帮助将不胜感激。

编辑:

我更改了代码以检查LiveData和Observer是否为空,然后仅对其进行初始化。但这无济于事,它仍然被多次调用。

if (mTablesData == null){
        mData = mViewModel.getTablesData(mLocationID);

        if (mObserver == null){
            mObserver = tablesModels -> {
                if (tablesModels != null) {
                    mTablesRecyclerAdapter.addTables(tablesModels);
                    Log.e(LOG_TAG, "setUpUserRecyclerView: tablesModels");
                }
            };

            mData.observe(this, mObserver);
        }

    }

编辑2:

也尝试过此方法,但效果不佳:

   mTablesData = mViewModel.getTablesData(mLocationID);

    mObserver = tablesModels -> {
        if (tablesModels != null) {
            mTablesRecyclerAdapter.addTables(tablesModels);
            Log.e(LOG_TAG, "setUpRecyclerView: tablesModels");
        }
    };

    if (!mTablesData.hasObservers()) {
        mTablesData.observe(this, mObserver);
    }

3 个答案:

答案 0 :(得分:1)

首先,如果我理解正确,请使用RecyclerView,并将RecyclerViewsetUpUserRecyclerView();中每个片段的onCreate()方法用作其ViewModel。因此,如果您有3个片段,则将有3个观察者。如果要让所有人都使用Activity中的ViewModelProviders.of(getActivity(), factory),则必须将父活动指向此处-> observeForever

第二,为什么要在存储库中使用observe?您可以只使用PeriodicWorkRequest吗?

最后,如果您想每30秒运行一次此请求,为什么不使用WorkManager-> https://developer.android.com/topic/libraries/architecture/workmanager/basics#java中的{{1}}

希望我能有所帮助:)

答案 1 :(得分:1)

所以我们从注释中的实验中学到了什么,您需要在观察mTablesData之前先检查它是否已经被观察到,并仅在未被观察到时进行观察,例如

if (!mTablesData.hasObservers()) { mTablesData.observeForever(tablesModels -> { ...

答案 2 :(得分:0)

我认为您需要将mObserver包装在CompositeDisposable中。

CompositeDisposable disposable = new CompositeDisposable();

disposable.add(mObserver);

@Override
public void onDestroy() {
   mData.removeObserver(mObserver);
   disposable.clear();
   super.onDestroy();
}

希望对您有帮助。