From c1e1236b647831b32a4b5fce6b44736fd3b844c1 Mon Sep 17 00:00:00 2001 From: Valentin Hinov Date: Mon, 23 Sep 2019 12:57:43 +0100 Subject: [PATCH] Issue #288 Use hasSameContentAs for comparing Item equality --- .../java/com/xwray/groupie/DiffCallback.java | 2 +- .../src/main/java/com/xwray/groupie/Item.java | 16 ++++ .../main/java/com/xwray/groupie/Section.java | 8 +- .../java/com/xwray/groupie/UpdatingGroup.java | 6 +- .../test/java/com/xwray/groupie/ItemTest.java | 86 +++++++++++++++++-- 5 files changed, 104 insertions(+), 14 deletions(-) diff --git a/library/src/main/java/com/xwray/groupie/DiffCallback.java b/library/src/main/java/com/xwray/groupie/DiffCallback.java index b68af4a4..88188cb4 100644 --- a/library/src/main/java/com/xwray/groupie/DiffCallback.java +++ b/library/src/main/java/com/xwray/groupie/DiffCallback.java @@ -39,7 +39,7 @@ public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { Item oldItem = GroupUtils.getItem(oldGroups, oldItemPosition); Item newItem = GroupUtils.getItem(newGroups, newItemPosition); - return newItem.equals(oldItem); + return newItem.hasSameContentAs(oldItem); } @Nullable diff --git a/library/src/main/java/com/xwray/groupie/Item.java b/library/src/main/java/com/xwray/groupie/Item.java index 12307321..c5a1d59a 100644 --- a/library/src/main/java/com/xwray/groupie/Item.java +++ b/library/src/main/java/com/xwray/groupie/Item.java @@ -188,6 +188,8 @@ public long getId() { * even if there has been a change in that data. *

* The default implementation compares both view type and id. + * + * @return True if the items are the same, false otherwise. */ public boolean isSameAs(Item other) { if (getViewType() != other.getViewType()) { @@ -196,6 +198,20 @@ public boolean isSameAs(Item other) { return getId() == other.getId(); } + /** + * Whether this item has the same content as another when compared using DiffUtil. + * + * After two items have been determined to be the same using {@link #isSameAs(Item)} this function + * should check whether their contents are the same. + * + * The default implementation does this using {@link #equals(Object)} + * + * @return True if both items have the same content, false otherwise + */ + public boolean hasSameContentAs(Item other) { + return this.equals(other); + } + @Nullable public Object getChangePayload(Item newItem) { return null; diff --git a/library/src/main/java/com/xwray/groupie/Section.java b/library/src/main/java/com/xwray/groupie/Section.java index d1a314d4..2d14e07d 100644 --- a/library/src/main/java/com/xwray/groupie/Section.java +++ b/library/src/main/java/com/xwray/groupie/Section.java @@ -132,9 +132,9 @@ public void clear() { *

* Item comparisons are made using: * - Item.isSameAs(Item otherItem) (are items the same?) - * - Item.equals() (are contents the same?) + * - Item.hasSameContentAs() (are contents the same?) *

- * If you don't customize getId() or isSameAs() and equals(), the default implementations will return false, + * If you don't customize getId() or isSameAs() and hasSameContentAs(), the default implementations will return false, * meaning your Group will consider every update a complete change of everything. * * This will default detectMoves to true. @@ -152,9 +152,9 @@ public void update(@NonNull final Collection newBodyGroups) { *

* Item comparisons are made using: * - Item.isSameAs(Item otherItem) (are items the same?) - * - Item.equals() (are contents the same?) + * - Item.hasSameContentAs() (are contents the same?) *

- * If you don't customize getId() or isSameAs() and equals(), the default implementations will return false, + * If you don't customize getId() or isSameAs() and hasSameContentAs(), the default implementations will return false, * meaning your Group will consider every update a complete change of everything. * * @param newBodyGroups The new content of the section diff --git a/library/src/main/java/com/xwray/groupie/UpdatingGroup.java b/library/src/main/java/com/xwray/groupie/UpdatingGroup.java index 0e3ba952..3e48fbc2 100644 --- a/library/src/main/java/com/xwray/groupie/UpdatingGroup.java +++ b/library/src/main/java/com/xwray/groupie/UpdatingGroup.java @@ -16,8 +16,8 @@ *

* Item comparisons are made using: * - Item.getId() (are items the same?) - * - Item.equals() (are contents the same?) - * If you don't customize getId() or equals(), the default implementations will return false, + * - Item.hasSameContentAs() (are contents the same?) + * If you don't customize getId() or hasSameContentAs(), the default implementations will return false, * meaning your Group will consider every update a complete change of everything. */ @Deprecated @@ -108,7 +108,7 @@ public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { Item oldItem = items.get(oldItemPosition); Item newItem = newList.get(newItemPosition); - return oldItem.equals(newItem); + return oldItem.hasSameContentAs(newItem); } } } diff --git a/library/src/test/java/com/xwray/groupie/ItemTest.java b/library/src/test/java/com/xwray/groupie/ItemTest.java index be303d33..b4b17180 100644 --- a/library/src/test/java/com/xwray/groupie/ItemTest.java +++ b/library/src/test/java/com/xwray/groupie/ItemTest.java @@ -1,12 +1,17 @@ package com.xwray.groupie; -import junit.framework.Assert; +import androidx.annotation.NonNull; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; +import java.util.Objects; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; import static org.mockito.Mockito.verify; @RunWith(MockitoJUnitRunner.class) @@ -16,16 +21,16 @@ public class ItemTest { GroupAdapter groupAdapter; @Test - public void selfPositionIs0() throws Exception { + public void selfPositionIs0() { Item item = new DummyItem(); - Assert.assertEquals(0, item.getPosition(item)); + assertEquals(0, item.getPosition(item)); } @Test - public void positionIsNegative1IfItemIsNotSelf() throws Exception { + public void positionIsNegative1IfItemIsNotSelf() { Item item = new DummyItem(); Item differentItem = new DummyItem(); - Assert.assertEquals(-1, item.getPosition(differentItem)); + assertEquals(-1, item.getPosition(differentItem)); } @Test @@ -36,4 +41,73 @@ public void notifyChangeNotifiesParentObserver() { verify(groupAdapter).onItemChanged(item, 0); } + + @Test + public void isSameAsFailsIfViewTypeIsDifferent() { + final DataItem itemA = new DataItem(0, 1, 0); + final DataItem itemB = new DataItem(1, 1, 0); + + assertFalse(itemA.isSameAs(itemB)); + } + + @Test + public void isSameAsSucceedsIfIdMatches() { + final DataItem itemA = new DataItem(1, 1, 0); + final DataItem itemB = new DataItem(1, 1, 0); + final DataItem itemC = new DataItem(1, 2, 0); + + assertTrue(itemA.isSameAs(itemB)); + assertFalse(itemA.isSameAs(itemC)); + } + + @Test + public void hasSameContentAsUsesEqualsByDefault() { + final DataItem itemA = new DataItem(0, 1, 2); + final DataItem itemB = new DataItem(0, 1, 2); + final DataItem itemC = new DataItem(0, 1, 3); + + assertTrue(itemA.hasSameContentAs(itemB)); + assertFalse(itemA.hasSameContentAs(itemC)); + } + + private static class DataItem extends Item { + + private int layout; + private long id; + private int equalsComparison; + + DataItem(int layout, long id, int equalsComparison) { + this.layout = layout; + this.id = id; + this.equalsComparison = equalsComparison; + } + + @Override + public void bind(@NonNull ViewHolder viewHolder, int position) { + + } + + @Override + public long getId() { + return id; + } + + @Override + public int getLayout() { + return layout; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DataItem dataItem = (DataItem) o; + return equalsComparison == dataItem.equalsComparison; + } + + @Override + public int hashCode() { + return Objects.hash(equalsComparison); + } + } } \ No newline at end of file