Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions library/src/main/java/com/xwray/groupie/DiffCallback.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package com.xwray.groupie;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DiffUtil;

import java.util.Collection;
import java.util.Collections;

class DiffCallback extends DiffUtil.Callback {
private final int oldBodyItemCount;
private final int newBodyItemCount;
private final Collection<? extends Group> oldGroups;
private final Collection<? extends Group> newGroups;

DiffCallback(@NonNull Group oldGroup, @NonNull Group newGroup) {
this(Collections.singletonList(oldGroup), Collections.singletonList(newGroup));
}

DiffCallback(Collection<? extends Group> oldGroups, Collection<? extends Group> newGroups) {
this.oldBodyItemCount = GroupUtils.getItemCount(oldGroups);
this.newBodyItemCount = GroupUtils.getItemCount(newGroups);
Expand Down
87 changes: 63 additions & 24 deletions library/src/main/java/com/xwray/groupie/Section.java
Original file line number Diff line number Diff line change
Expand Up @@ -378,70 +378,109 @@ private boolean isPlaceholderShown() {
}

public void setHeader(@NonNull Group header) {
//noinspection ConstantConditions
if (header == null)
throw new NullPointerException("Header can't be null. Please use removeHeader() instead!");
if (this.header != null) {
this.header.unregisterGroupDataObserver(this);
}
int previousHeaderItemCount = getHeaderItemCount();

Group previousHeader = this.header;
this.header = header;
header.registerGroupDataObserver(this);
notifyHeaderItemsChanged(previousHeaderItemCount);
notifyHeaderItemsChanged(previousHeader, header);
}

public void removeHeader() {
if (this.header == null) {
return;
}

Group header = this.header;
this.header.unregisterGroupDataObserver(this);
int previousHeaderItemCount = getHeaderItemCount();
this.header = null;
notifyHeaderItemsChanged(previousHeaderItemCount);
notifyHeaderItemsChanged(header, null);
}

private void notifyHeaderItemsChanged(int previousHeaderItemCount) {
int newHeaderItemCount = getHeaderItemCount();
if (previousHeaderItemCount > 0) {
notifyItemRangeRemoved(0, previousHeaderItemCount);
}
if (newHeaderItemCount > 0) {
notifyItemRangeInserted(0, newHeaderItemCount);
}
private void notifyHeaderItemsChanged(
@Nullable final Group previousHeader,
@Nullable final Group newHeader
) {
notifyHeaderOrFooterChanged(0, previousHeader, newHeader);
}


public void setFooter(@NonNull Group footer) {
//noinspection ConstantConditions
if (footer == null)
throw new NullPointerException("Footer can't be null. Please use removeFooter() instead!");
if (this.footer != null) {
this.footer.unregisterGroupDataObserver(this);
}
int previousFooterItemCount = getFooterItemCount();

Group previousFooter = this.footer;
this.footer = footer;
footer.registerGroupDataObserver(this);
notifyFooterItemsChanged(previousFooterItemCount);
notifyFooterItemsChanged(previousFooter, footer);
}

public void removeFooter() {
if (this.footer == null) {
return;
}

Group previousFooter = this.footer;
this.footer.unregisterGroupDataObserver(this);
int previousFooterItemCount = getFooterItemCount();
this.footer = null;
notifyFooterItemsChanged(previousFooterItemCount);
notifyFooterItemsChanged(previousFooter, null);
}

private void notifyFooterItemsChanged(int previousFooterItemCount) {
int newFooterItemCount = getFooterItemCount();
if (previousFooterItemCount > 0) {
notifyItemRangeRemoved(getItemCountWithoutFooter(), previousFooterItemCount);
}
if (newFooterItemCount > 0) {
notifyItemRangeInserted(getItemCountWithoutFooter(), newFooterItemCount);
private void notifyFooterItemsChanged(
@Nullable Group previousFooter,
@Nullable Group newFooter
) {
notifyHeaderOrFooterChanged(getItemCountWithoutFooter(), previousFooter, newFooter);
}

private void notifyHeaderOrFooterChanged(
final int positionStart,
@Nullable final Group prevGroup,
@Nullable final Group newGroup
) {
final int previousHeaderItemCount = prevGroup == null ? 0 : prevGroup.getItemCount();
final int newHeaderItemCount = newGroup == null ? 0 : newGroup.getItemCount();

if (previousHeaderItemCount == 0 && newHeaderItemCount == 0) return;
if (previousHeaderItemCount == 0) {
notifyItemRangeInserted(positionStart, newHeaderItemCount);
return;
} else if (newHeaderItemCount == 0) {
notifyItemRangeRemoved(positionStart, previousHeaderItemCount);
return;
}

DiffUtil.Callback callback = new DiffCallback(prevGroup, newGroup);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback, true);
diffResult.dispatchUpdatesTo(new ListUpdateCallback() {
@Override
public void onInserted(int position, int count) {
notifyItemRangeInserted(position + positionStart, count);
}

@Override
public void onRemoved(int position, int count) {
notifyItemRangeRemoved(position + positionStart, count);
}

@Override
public void onMoved(int fromPosition, int toPosition) {
notifyItemMoved(fromPosition + positionStart, toPosition + positionStart);
}

@Override
public void onChanged(int position, int count, @Nullable Object payload) {
notifyItemRangeChanged(position + positionStart, count, payload);
}
});
}

public void setHideWhenEmpty(boolean hide) {
Expand Down