Bug 1278644 - Stable getItemId implementation for CombinedHistoryAdapter r=sebastian
MozReview-Commit-ID: EylBNeI9Xwp
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
@@ -45,16 +45,17 @@ public class CombinedHistoryAdapter exte
// We use a sparse array to store each section header's position in the panel [more cheaply than a HashMap].
private final SparseArray<SectionHeader> sectionHeaders;
public CombinedHistoryAdapter(Resources resources) {
super();
sectionHeaders = new SparseArray<>();
HistorySectionsHelper.updateRecentSectionOffset(resources, sectionDateRangeArray);
+ this.setHasStableIds(true);
}
public void setHistory(Cursor history) {
historyCursor = history;
populateSectionHeaders(historyCursor, sectionHeaders);
notifyDataSetChanged();
}
@@ -185,16 +186,62 @@ public class CombinedHistoryAdapter exte
@Override
public int getItemCount() {
final int historySize = historyCursor == null ? 0 : historyCursor.getCount();
return historySize + sectionHeaders.size() + CombinedHistoryPanel.NUM_SMART_FOLDERS;
}
/**
+ * Returns stable ID for each position. Data behind historyCursor is a sorted Combined view.
+ *
+ * @param position view item position for which to generate a stable ID
+ * @return stable ID for given position
+ */
+ @Override
+ public long getItemId(int position) {
+ // Two randomly selected large primes used to generate non-clashing IDs.
+ final long PRIME_BOOKMARKS = 32416189867L;
+ final long PRIME_SECTION_HEADERS = 32416187737L;
+
+ // RecyclerView.NO_ID is -1, so let's start from -2 for our hard-coded IDs.
+ final int RECENT_TABS_ID = -2;
+ final int SYNCED_DEVICES_ID = -3;
+
+ switch (getItemTypeForPosition(position)) {
+ case RECENT_TABS:
+ return RECENT_TABS_ID;
+ case SYNCED_DEVICES:
+ return SYNCED_DEVICES_ID;
+ case SECTION_HEADER:
+ // We might have multiple section headers, so we try get unique IDs for them.
+ return position * PRIME_SECTION_HEADERS;
+ case HISTORY:
+ if (!historyCursor.moveToPosition(position)) {
+ return RecyclerView.NO_ID;
+ }
+
+ final int historyIdCol = historyCursor.getColumnIndexOrThrow(BrowserContract.Combined.HISTORY_ID);
+ final long historyId = historyCursor.getLong(historyIdCol);
+
+ if (historyId != -1) {
+ return historyId;
+ }
+
+ final int bookmarkIdCol = historyCursor.getColumnIndexOrThrow(BrowserContract.Combined.BOOKMARK_ID);
+ final long bookmarkId = historyCursor.getLong(bookmarkIdCol);
+
+ // Avoid clashing with historyId.
+ return bookmarkId * PRIME_BOOKMARKS;
+ default:
+ throw new IllegalStateException("Unexpected Home Panel item type");
+ }
+ }
+
+ /**
* Add only the SectionHeaders that have history items within their range to a SparseArray, where the
* array index is the position of the header in the history-only (no clients) ordering.
* @param c data Cursor
* @param sparseArray SparseArray to populate
*/
private static void populateSectionHeaders(Cursor c, SparseArray<SectionHeader> sparseArray) {
sparseArray.clear();