RecyclerView RecyclerViewDataObserver was not registered

Mulgard picture Mulgard · Mar 14, 2016 · Viewed 9.2k times · Source

Im working with RecyclerView, SyncAdapter and greenrobot eventbus When my SyncAdapter finished syincing i post a message into the message bus:

EventBus.getDefault().post(new EventMessagesRefreshed());

In my target class i do the following:

@Subscribe
public void onEvent(EventMessagesRefreshed event) {
    this.init();
}

And in my init() i create the adapter for the recyclerview and set it:

public void init() {
    if(this.listRowParent != null) {
        this.adapter = new FragmentMessagesListAdapter(this.getActivity(), SingletonMessages.getInstance().getMessages());
        this.listRowParent.setAdapter(this.adapter);
    }
}

// listRowParent is my RecyclerView!

The fragment which receives the event is inside a of a tab view. So there are multiple tabs and sometimes ofcourse the SyncAdapter posts the EventMessagesRefreshed into the message bus when im not in the correct target tab but since it is registered it tries to call init() and to create the adapter and set it to the RecyclerView. If that happens i get the following error:

Could not dispatch event: class EventMessagesRefreshed to subscribing class class FragmentMessagesList
java.lang.IllegalStateException: Observer android.support.v7.widget.RecyclerView$RecyclerViewDataObserver@2c3421a7 was not registered.
    at android.database.Observable.unregisterObserver(Observable.java:69)
    at android.support.v7.widget.RecyclerView$Adapter.unregisterAdapterDataObserver(RecyclerView.java:5688)
    at android.support.v7.widget.RecyclerView.setAdapterInternal(RecyclerView.java:873)
    at android.support.v7.widget.RecyclerView.setAdapter(RecyclerView.java:857)

So i need to init() my adapter and RecyclerView only when the RecyclerViewDataObserver is registered.

How can i do that?

Answer

Pavitra Kansara picture Pavitra Kansara · Mar 14, 2016

You need to register Data observer to listen to data changes from sync adapter.

mRecyclerViewAdapter.registerAdapterDataObserver(myObserver);

RecyclerView.AdapterDataObserver are a result of which notify methods you call. So for instance if you call notifyItemInserted() after you add an item to your adapter then onItemRangeInserted() will get called

A more detailed example

protected void setupRecyclerView() {
    mAdapter = new MyAdapter(mItemList);
    mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            checkAdapterIsEmpty();
        }
    });

    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    mRecyclerView.setHasFixedSize(true);

    mRecyclerView.setAdapter(mAdapter);
    checkAdapterIsEmpty();
}`

The adapter may publish a variety of events describing specific changes. Not all adapters may support all change types and some may fall back to a generic "something changed" event if more specific data is not available.