Skip to content

Instantly share code, notes, and snippets.

Created November 24, 2019 21:02
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
This is the Java version of NickHolcombe's ListAdapterWithHeader which was originally wrote in Kotlin, after spending countless hours online looking for a way to add a header to my PagedListAdapter I finally found a solution except it was in Kotlin, I managed to rewrite it in …
import androidx.recyclerview.widget.AsyncDifferConfig;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListUpdateCallback;
import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import kotlin.jvm.internal.Intrinsics;
* {@link RecyclerView.Adapter RecyclerView.Adapter} base class based on
* {@link ListAdapter} for presenting List data with header rows in a
* {@link RecyclerView}, including computing diffs between Lists on a background thread.
* @param <T> Type of the Lists this Adapter will receive.
* @param <VH> A class that extends ViewHolder that will be used by the adapter.
* @param diffCallback DiffUtil.ItemCallback<T> class used by DiffUtils for comparing <T> items
* @param headerOffset Int number of header rows before list
public abstract class ListAdapterWithHeader<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private int headerOffset = 1;
private AsyncListDiffer<T> asyncListDiffer;
public ListAdapterWithHeader(DiffUtil.ItemCallback<T> diffCallback) {
this.asyncListDiffer = new AsyncListDiffer<>(new OffsetListUpdateCallback(this, headerOffset),
new AsyncDifferConfig.Builder<>(diffCallback).build());
public void submitList(List<T> items) {
private List<T> getCurrentList() {
return asyncListDiffer.getCurrentList();
public final T getItem(int position) {
return this.asyncListDiffer.getCurrentList().get(position - this.headerOffset);
public int getItemCount() {
return this.asyncListDiffer.getCurrentList().size() + this.headerOffset;
private final class OffsetListUpdateCallback implements ListUpdateCallback {
private final RecyclerView.Adapter adapter;
private final int offset;
OffsetListUpdateCallback(@NotNull RecyclerView.Adapter adapter, int offset) {
Intrinsics.checkParameterIsNotNull(adapter, "adapter");
this.adapter = adapter;
this.offset = offset;
final int offsetPosition(int originalPosition) {
return originalPosition + this.offset;
public void onInserted(int position, int count) {
this.adapter.notifyItemRangeInserted(this.offsetPosition(position), count);
public void onRemoved(int position, int count) {
this.adapter.notifyItemRangeRemoved(this.offsetPosition(position), count);
public void onMoved(int fromPosition, int toPosition) {
this.adapter.notifyItemMoved(this.offsetPosition(fromPosition), this.offsetPosition(toPosition));
public void onChanged(int position, int count, @Nullable Object payload) {
this.adapter.notifyItemRangeChanged(this.offsetPosition(position), count, payload);
Copy link

Great, thanks

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