diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DataCellItem.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DataCellItem.java index ecb9f0c..7468cc1 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DataCellItem.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DataCellItem.java @@ -1,6 +1,6 @@ package com.infullmobile.android.recyclerviewwithdynamicsubtitles; -public class DataCellItem implements ListItem { +class DataCellItem implements ListItem { private T data; diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DynamicRecyclerViewAdapter.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DynamicRecyclerViewAdapter.java index 2ce9b29..cddf0f8 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DynamicRecyclerViewAdapter.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/DynamicRecyclerViewAdapter.java @@ -57,16 +57,17 @@ public final int getItemViewType(int position) { public final int getItemCount() { return sectionedItemList.size(); } - + public final void setData(@Nullable Collection items, @NonNull SectionEvaluator sectionEvaluator) { - setData(items, sectionEvaluator, Comparators.ASCENDING_COMPARATOR); + setData(items, sectionEvaluator, SectionComparators.ASCENDING_COMPARATOR, new EmptyItemComparator()); } public final void setData(@Nullable Collection items, @NonNull SectionEvaluator sectionEvaluator, - @NonNull Comparator
comparator) { - final SectionedItems sectionedItems = new SectionedItems<>(sectionEvaluator, items, comparator); + @NonNull Comparator
sectionComparator, + @NonNull Comparator dataObjectComparator) { + final SectionedItems sectionedItems = new SectionedItems<>(sectionEvaluator, items, sectionComparator, dataObjectComparator); mapOfSections = sectionedItems.getSections(); insertNewItems(sectionedItems); } diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/EmptyItemComparator.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/EmptyItemComparator.java new file mode 100644 index 0000000..80353be --- /dev/null +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/EmptyItemComparator.java @@ -0,0 +1,11 @@ +package com.infullmobile.android.recyclerviewwithdynamicsubtitles; + +import java.util.Comparator; + +public class EmptyItemComparator implements Comparator { + + @Override + public int compare(DataObject lhs, DataObject rhs) { + return 0; + } +} diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ListItem.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ListItem.java index bddb654..b0a48d8 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ListItem.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ListItem.java @@ -1,5 +1,5 @@ package com.infullmobile.android.recyclerviewwithdynamicsubtitles; -public interface ListItem { +interface ListItem { boolean isHeader(); } diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Section.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Section.java index 2722870..8b257da 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Section.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Section.java @@ -8,17 +8,17 @@ import java.util.Collection; import java.util.List; -public class Section { +class Section { private final List items; private final List dataItems; private final String title; - public Section(@NonNull T firstItem, @NonNull String title) { + Section(@NonNull T firstItem, @NonNull String title) { this(Arrays.asList(firstItem), title); } - public Section(@NonNull List items, @NonNull String title) { + Section(@NonNull List items, @NonNull String title) { this.title = title; dataItems = new ArrayList<>(items); this.items = createListItems(title, items); @@ -33,22 +33,22 @@ private List createListItems(String title, List items) { return listItems; } - public void addNewItem(@Nullable T item) { + void addNewItem(@Nullable T item) { if (item != null) { dataItems.add(item); items.add(new DataCellItem<>(item)); } } - public String getTitle() { + String getTitle() { return title; } - public Collection getListItems() { + Collection getListItems() { return items; } - public Collection getDataItems() { + Collection getDataItems() { return dataItems; } } diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Comparators.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionComparators.java similarity index 92% rename from recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Comparators.java rename to recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionComparators.java index fbbab5f..fd84058 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/Comparators.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionComparators.java @@ -2,9 +2,9 @@ import java.util.Comparator; -public final class Comparators { +public final class SectionComparators { - private Comparators() { + private SectionComparators() { throw new AssertionError("No instances."); } diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionHeaderItem.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionHeaderItem.java index 45a71e6..b968c7d 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionHeaderItem.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionHeaderItem.java @@ -1,6 +1,6 @@ package com.infullmobile.android.recyclerviewwithdynamicsubtitles; -public class SectionHeaderItem implements ListItem { +class SectionHeaderItem implements ListItem { private final String sectionName; @@ -8,7 +8,7 @@ public class SectionHeaderItem implements ListItem { this.sectionName = sectionName; } - public String getSectionName() { + String getSectionName() { return sectionName; } diff --git a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItems.java b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItems.java index 33c9a84..c931025 100644 --- a/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItems.java +++ b/recyclerviewwithdynamicsubtitles/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItems.java @@ -12,24 +12,27 @@ import java.util.List; import java.util.Map; -public class SectionedItems { +class SectionedItems { private final SectionEvaluator sectionEvaluator; private List> listOfOrderedSections = Collections.emptyList(); SectionedItems(@NonNull SectionEvaluator sectionEvaluator, @Nullable Collection items, - @NonNull Comparator
comparator) { + @NonNull Comparator
sectionComparator, + @NonNull Comparator dataObjectComparator) { this.sectionEvaluator = sectionEvaluator; - setData(items, comparator); + setData(items, sectionComparator, dataObjectComparator); } - private void setData(@Nullable Collection items, @NonNull Comparator
comparator) { + private void setData(@Nullable Collection items, + @NonNull Comparator
sectionComparator, + @NonNull Comparator dataObjectComparator) { listOfOrderedSections.clear(); - listOfOrderedSections = itemsToSections(items, comparator); + listOfOrderedSections = itemsToSections(items, sectionComparator, dataObjectComparator); } - public List getItems() { + List getItems() { final List result = new ArrayList<>(); for (Section section : listOfOrderedSections) { result.addAll(section.getListItems()); @@ -37,7 +40,7 @@ public List getItems() { return result; } - public Map> getSections() { + Map> getSections() { final Map> mapOfSections = new HashMap<>(); for (Section section : listOfOrderedSections) { mapOfSections.put(section.getTitle(), section); @@ -45,6 +48,23 @@ public Map> getSections() { return mapOfSections; } + @NonNull + private List> itemsToSections(@Nullable Collection items, + @NonNull Comparator
sectionComparator, + @NonNull Comparator dataObjectComparator) { + return (items != null) + ? sortSections(getSectionsOfItems(sortItems(items, dataObjectComparator)), sectionComparator) + : Collections.>emptyList(); + } + + @NonNull + private List sortItems(@NonNull Collection items, + @NonNull Comparator comparator) { + final List listOfItems = new LinkedList<>(items); + Collections.sort(listOfItems, comparator); + return listOfItems; + } + @NonNull private List> sortSections(@NonNull Collection> sectionedItems, @NonNull Comparator
comparator) { @@ -53,13 +73,6 @@ private List> sortSections(@NonNull Collection> sectionedI return listOfSections; } - @NonNull - private List> itemsToSections(@Nullable Collection items, - @NonNull Comparator
comparator) { - return (items != null) ? sortSections(getSectionsOfItems(items), comparator) - : Collections.>emptyList(); - } - @NonNull private Collection> getSectionsOfItems(@Nullable Collection items) { final Map> mapOfAllAddedSections = new HashMap<>(); diff --git a/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/EmptyItemComparatorTest.java b/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/EmptyItemComparatorTest.java new file mode 100644 index 0000000..c57649f --- /dev/null +++ b/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/EmptyItemComparatorTest.java @@ -0,0 +1,35 @@ +package com.infullmobile.android.recyclerviewwithdynamicsubtitles; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EmptyItemComparatorTest { + + private static final String lowest = "aTitle"; + private static final String medium = "bTitle"; + private static final String highest = "cTitle"; + + private List listOfItems; + + @Before + public void setUp() throws Exception { + listOfItems = Arrays.asList(lowest, medium, highest); + } + + @Test + public void shouldReturnItemsInTheSameOrder() { + // when + Collections.sort(listOfItems, new EmptyItemComparator()); + + // then + assertThat(listOfItems.get(0)).isEqualTo(lowest); + assertThat(listOfItems.get(1)).isEqualTo(medium); + assertThat(listOfItems.get(2)).isEqualTo(highest); + } +} diff --git a/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ComparatorsTest.java b/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionComparatorsTest.java similarity index 86% rename from recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ComparatorsTest.java rename to recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionComparatorsTest.java index 821a6df..6cfd21b 100644 --- a/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/ComparatorsTest.java +++ b/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionComparatorsTest.java @@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; -public class ComparatorsTest { +public class SectionComparatorsTest { private static final Section lowest = new Section<>("item", "aTitle"); private static final Section medium = new Section<>("item", "bTitle"); @@ -25,7 +25,7 @@ public void setUp() throws Exception { @Test public void ascedingComparatorShouldCompareSectionsAscedning() { // when - Collections.sort(listOfSections, Comparators.ASCENDING_COMPARATOR); + Collections.sort(listOfSections, SectionComparators.ASCENDING_COMPARATOR); // then assertThat(listOfSections.get(0)).isEqualTo(lowest); @@ -36,7 +36,7 @@ public void ascedingComparatorShouldCompareSectionsAscedning() { @Test public void descedingComparatorShouldCompareSectionsDescending() { // when - Collections.sort(listOfSections, Comparators.DESCENDING_COMPARATOR); + Collections.sort(listOfSections, SectionComparators.DESCENDING_COMPARATOR); // then assertThat(listOfSections.get(0)).isEqualTo(highest); diff --git a/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItemsTest.java b/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItemsTest.java index 83adedb..eefadc4 100644 --- a/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItemsTest.java +++ b/recyclerviewwithdynamicsubtitles/src/test/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/SectionedItemsTest.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; @@ -17,9 +18,15 @@ public class SectionedItemsTest { private static final String FIRST_ITEM = "firstItem"; private final static String SECOND_ITEM = "secondItem"; private final static String SECOND_SECOND_ITEM = "secondsecondItem"; + private static final String FIRST_IN_ALPHABETICAL_ORDER_ITEM = "A"; + private static final String SECOND_IN_ALPHABETICAL_ORDER_ITEM = "B"; + private static final String THIRD_IN_ALPHABETICAL_ORDER_ITEM = "C"; private final static int TWO_HEADER_AND_THREE_ITEMS = 5; List testItems = Arrays.asList(FIRST_ITEM, SECOND_ITEM, SECOND_SECOND_ITEM); + List mixedUpTestItems = Arrays.asList(THIRD_IN_ALPHABETICAL_ORDER_ITEM, + FIRST_IN_ALPHABETICAL_ORDER_ITEM, + SECOND_IN_ALPHABETICAL_ORDER_ITEM); @Test public void shouldCreateCorrectSectionedItemsWithTwoSections() { @@ -27,7 +34,8 @@ public void shouldCreateCorrectSectionedItemsWithTwoSections() { sectionedItems = new SectionedItems<>( new FirstLetterSectionEvaluator(), testItems, - Comparators.ASCENDING_COMPARATOR); + SectionComparators.ASCENDING_COMPARATOR, + new EmptyItemComparator()); // when List listItems = sectionedItems.getItems(); @@ -53,7 +61,8 @@ public void shouldCreateCorrectSectionedItemsFromNullItems() { sectionedItems = new SectionedItems<>( new FirstLetterSectionEvaluator(), null, - Comparators.ASCENDING_COMPARATOR); + SectionComparators.ASCENDING_COMPARATOR, + new EmptyItemComparator()); // when List listItems = sectionedItems.getItems(); @@ -70,7 +79,8 @@ public void shouldCreateCorrectSectionedItemsFromEmptyList() { sectionedItems = new SectionedItems<>( new FirstLetterSectionEvaluator(), Collections.emptyList(), - Comparators.ASCENDING_COMPARATOR); + SectionComparators.ASCENDING_COMPARATOR, + new EmptyItemComparator()); // when List listItems = sectionedItems.getItems(); @@ -78,10 +88,27 @@ public void shouldCreateCorrectSectionedItemsFromEmptyList() { // then assertThat(listItems).isEmpty(); - assertThat(mapOfSections).isEmpty(); } + @Test + public void shouldReturnItemsInAlphabeticalOrder() { + // given + sectionedItems = new SectionedItems<>( + new FirstLetterSectionEvaluator(), + mixedUpTestItems, + SectionComparators.ASCENDING_COMPARATOR, + new AlphabeticalOrderItemComparator()); + + // when + List orderedItems = sectionedItems.getItems(); + + // then + assertThat(((SectionHeaderItem) orderedItems.get(0)).getSectionName()).isEqualTo(FIRST_IN_ALPHABETICAL_ORDER_ITEM); + assertThat(((SectionHeaderItem) orderedItems.get(2)).getSectionName()).isEqualTo(SECOND_IN_ALPHABETICAL_ORDER_ITEM); + assertThat(((SectionHeaderItem) orderedItems.get(4)).getSectionName()).isEqualTo(THIRD_IN_ALPHABETICAL_ORDER_ITEM); + } + private static class FirstLetterSectionEvaluator implements SectionEvaluator { @Override @@ -91,4 +118,11 @@ public String evaluate(String string) { : "/empty"; } } + + private static class AlphabeticalOrderItemComparator implements Comparator { + @Override + public int compare(String lhs, String rhs) { + return lhs.compareTo(rhs); + } + } } \ No newline at end of file diff --git a/sample/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/sample/MainActivity.java b/sample/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/sample/MainActivity.java index 450799a..98df496 100644 --- a/sample/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/sample/MainActivity.java +++ b/sample/src/main/java/com/infullmobile/android/recyclerviewwithdynamicsubtitles/sample/MainActivity.java @@ -1,15 +1,17 @@ package com.infullmobile.android.recyclerviewwithdynamicsubtitles.sample; -import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; +import com.infullmobile.android.recyclerviewwithdynamicsubtitles.SectionComparators; import com.infullmobile.android.recyclerviewwithdynamicsubtitles.SectionEvaluator; import com.infullmobile.android.recyclerviewwithdynamicsubtitles.sample.model.Book; import com.infullmobile.android.recyclerviewwithdynamicsubtitles.sample.model.BookFactory; +import java.util.Comparator; import java.util.List; public class MainActivity extends AppCompatActivity implements MyDynamicTitlesAdapter.ItemEraseListener { @@ -24,6 +26,12 @@ public String evaluate(Book book) { return book.getGenre(); } }; + private Comparator itemsComparator = new Comparator() { + @Override + public int compare(Book lhs, Book rhs) { + return lhs.getTitle().compareTo(rhs.getTitle()); + } + }; @Override protected void onCreate(Bundle savedInstanceState) { @@ -62,6 +70,6 @@ public void eraseItem(Book book) { } private void refreshAdapter() { - myDynamicTitlesAdapter.setData(books, sectionEvaluator); + myDynamicTitlesAdapter.setData(books, sectionEvaluator, SectionComparators.ASCENDING_COMPARATOR, itemsComparator); } }