Skip to content

Instantly share code, notes, and snippets.

@meoyawn
Created November 1, 2014 11:20
Show Gist options
  • Save meoyawn/31c8f054d1af4588dc5c to your computer and use it in GitHub Desktop.
Save meoyawn/31c8f054d1af4588dc5c to your computer and use it in GitHub Desktop.
RecyclerView doesn't have an emptyView support, we gotta fix that
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EmptyRecyclerView extends RecyclerView {
@Nullable View emptyView;
public EmptyRecyclerView(Context context) { super(context); }
public EmptyRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); }
public EmptyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
void checkIfEmpty() {
if (emptyView != null) {
emptyView.setVisibility(getAdapter().getItemCount() > 0 ? GONE : VISIBLE);
}
}
final @NotNull AdapterDataObserver observer = new AdapterDataObserver() {
@Override public void onChanged() {
super.onChanged();
checkIfEmpty();
}
};
@Override public void setAdapter(@Nullable Adapter adapter) {
final Adapter oldAdapter = getAdapter();
if (oldAdapter != null) {
oldAdapter.unregisterAdapterDataObserver(observer);
}
super.setAdapter(adapter);
if (adapter != null) {
adapter.registerAdapterDataObserver(observer);
}
}
public void setEmptyView(@Nullable View emptyView) {
this.emptyView = emptyView;
checkIfEmpty();
}
}
@AnirudhaAgashe
Copy link

Consider adding onItemRangeInserted and onItemRangeInserted to the observer

onChange is not fired when notifyItemRangeInserted and notifyItemRangeInserted is called on the adapter.

onItemRangeInserted, called when notifyItemRangeInserted).
Scenario: Initially the list is empty. But after adding items in range it will not be empty

onItemRangeRemoved to, called when notifyItemRangeRemoved is used.
Scenario: All the items might be removed from the data set and it may be empty

Thanks for the gist. I have forked you gist and added the above the changes. Also I have used Android's annotation instead of JetBrains to support Android Studio

@IlyaEremin
Copy link

Hi, you are a popular man!

@mobiRic
Copy link

mobiRic commented Sep 3, 2015

Hello, I would like to use this code in future projects of mine.

  • Are you the original author?

Would you be happy if I fork this and add an Apache v2 licence to my copy, with attribution to you?

Thanks,
Richard
Glowworm Software
Cape Town, South Africa

@meoyawn
Copy link
Author

meoyawn commented Sep 6, 2015

@mobiRic you can do whatever you want with this code :)

@mobiRic
Copy link

mobiRic commented Sep 7, 2015

Thanks - forked to https://gist.github.com/mobiRic/963a814d51259c730467

Can I suggest adding a method for swapAdapter() for completeness:

@Override
public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) {
    final Adapter oldAdapter = getAdapter();
    if (oldAdapter != null) {
        oldAdapter.unregisterAdapterDataObserver(observer);
    }

    if (adapter != null) {
        adapter.registerAdapterDataObserver(observer);
    }
    super.swapAdapter(adapter, removeAndRecycleExistingViews);
    checkIfEmpty();
}

@sevar83
Copy link

sevar83 commented Sep 11, 2015

@AnirudhaAgashe suggestion is correct!

@mmanishh
Copy link

mmanishh commented Oct 9, 2015

@notnul coudnl't resolve

@bryant1410
Copy link

maybe the emptyView attribute could be private

@subbuboyapati
Copy link

Hi @adelnizamutdinov , This we can achieve in flowing way.
Make two list item one for showing normal data and another one is for empty view

  1. In getitemcount, if count is zero return 1 otherwise size of an adapter.
  2. In itemViewType if size 0 return empty view type otherwise return your normal list item.

@Ghostish
Copy link

Really appreciate this great idea . It works well.

@Honghe
Copy link

Honghe commented Jul 13, 2016

adapter.notifyItemRemoved(position); will not evoke checkIfEmpty()

@wangyiyong
Copy link

But where is the emptyView attached?

@beraybentesen
Copy link

Does nothing when I use following method :
recyclerView.postDelayed(() -> Notify RecyclerView

Inflated like this :
View headerView = View.inflate(getActivity(), R.layout.layout_empty_view, null);

@josemigallas
Copy link

josemigallas commented Oct 13, 2017

@adelnizamutdinov
Hi, I think there's a small typo on line 25. Shouldn't it be @NonNull instead of @NotNull?

@josemigallas
Copy link

It is also not working without implementing onItemRangeInserted in the observer. I'm using FirebaseUI.

@Blablablar
Copy link

I have the same question, where is the emptyView attached?

@SohailZahidGit
Copy link

Its good but what happened if we had to add one more observer to for lazy loading/paging?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment