Are there any Observers written In RecyclerView.Adapter to know if dataset has been changed?

Nikhil picture Nikhil · Aug 31, 2016 · Viewed 8.6k times · Source

I have implemented my RecyclerView with it's Custom Adapter as follows

Global Declarations as follows

private LinearLayoutManager linearLayoutManager;
private int pastVisibleItems, visibleItemCount, totalItemCount;
private CustomRecyclerViewAdapter customRecyclerViewAdapter;

First I created Adapter Instance inside onCreate() method which has Empty Array inside it and set it to recyclerView

linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(
    Utility.ItemDecorationConst);
recyclerView.addItemDecoration(dividerItemDecoration);
customRecyclerViewAdapter = new CustomRecyclerViewAdapter(getActivity());

recyclerView.setAdapter(customRecyclerViewAdapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

    visibleItemCount = linearLayoutManager.getChildCount();
    totalItemCount = linearLayoutManager.getItemCount();
    pastVisibleItems = linearLayoutManager.findFirstVisibleItemPosition();
    if (loading) {
        if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
            loading = false;
            customRecyclerViewAdapter.addProgressBarEntry();
            controller.getNextPage(PublisherAppContainerFragment.this);
        }
    }
}
});

After rendering complete View when I get data from AsyncTask for filling in recyclerView

I call following method of the Adapter to fill data

customRecyclerViewAdapter.addAll(myArray);

note : addAll() is not any overridden method

following is code of my CustomRecyclerViewAdapter

class CustomRecyclerViewAdapter extends RecyclerView.Adapter<CustomRecyclerViewAdapter.ViewHolder> {
    ArrayList<MyModel> arrayList = new ArrayList<>();
    Context context;

    public CustomRecyclerViewAdapter(Context context) {
        this.context = context;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ViewHolder viewHolder = null;
        //inflated some view
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        //binded data to holder
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public void addAll(ArrayList myArray) {
        this.arrayList.addAll(myArray)
    }

    public void clear() {
        arrayList.clear();
    }
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public CardView cardView;

        public ViewHolder(View view) {
        super(view);
            this.cardView = (CardView) view.findViewById(R.id.card_view);
            this.cardView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
        //handle operations
        }
    }
}

So whenever I get data from AsynTask I call method addAll() and recyclerView works like charm.

Now, My question is how it's working very well even though I have never called notifyDataSetChanged() on the adapter. Are there any previously registered Observers for the adapter? who observes if the dataset which has been returned in public int getItemCount() has been changed?

As I have read from documentation

void notifyDataSetChanged ()

Notify any registered observers that the data set has changed.

that means even though there are some observers registered you need to notify them using notifyDataSetChanged(). Right?

I also called

boolean flag = customRecyclerViewAdapter.hasObservers();

to know if there are any observers registered? Flag is True.

So anyone would please help me understand how exactly these things work?

Answer

Gautam picture Gautam · Sep 8, 2016

If you look at the source of RecyclerView setAdapter call you will find a method setAdapterInternal(adapter, false, true);which is responsible for

Replaces the current adapter with the new one and triggers listeners.

This method is responsible for swapping the old adapter with the new one and internally it also registers for the custom Data Observer. This is the reason you are getting the flag as true