Forcing full data refresh when using custom object adapter.
Change-Id: I721ee032aece7109518583d836b29f621fc24b77
diff --git a/api/current.txt b/api/current.txt
index 7dc5ab7..1173f2b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2908,6 +2908,7 @@
method public final android.support.v17.leanback.widget.Presenter getPresenter(java.lang.Object);
method public final android.support.v17.leanback.widget.PresenterSelector getPresenterSelector();
method public final boolean hasStableIds();
+ method public boolean isImmediateNotifySupported();
method protected final void notifyChanged();
method protected final void notifyItemRangeChanged(int, int);
method protected final void notifyItemRangeInserted(int, int);
diff --git a/v17/leanback/src/android/support/v17/leanback/app/ListRowDataAdapter.java b/v17/leanback/src/android/support/v17/leanback/app/ListRowDataAdapter.java
index 5f18285..48a2d6a 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/ListRowDataAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/ListRowDataAdapter.java
@@ -1,6 +1,5 @@
package android.support.v17.leanback.app;
-import android.os.Handler;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.CursorObjectAdapter;
import android.support.v17.leanback.widget.ObjectAdapter;
@@ -26,39 +25,6 @@
private final ObjectAdapter mAdapter;
private int mLastVisibleRowIndex;
- private Handler mHandler;
- private Update mPendingUpdate;
- private int mPendingUpdateCount;
-
- private static class Update {
- int eventType;
- int positionStart;
- int itemCount;
-
- public Update(int type, int positionStart, int itemCount) {
- this.eventType = type;
- this.positionStart = positionStart;
- this.itemCount = itemCount;
- }
- }
-
- private Runnable notificationTask = new Runnable() {
- @Override
- public void run() {
- if (mPendingUpdateCount == 0) {
- return;
- } else if (mPendingUpdateCount == 1 && mPendingUpdate != null) {
- doNotify(
- mPendingUpdate.eventType,
- mPendingUpdate.positionStart,
- mPendingUpdate.itemCount);
- } else {
- notifyChanged();
- }
- mPendingUpdate = null;
- mPendingUpdateCount = 0;
- }
- };
public ListRowDataAdapter(ObjectAdapter adapter) {
super(adapter.getPresenterSelector());
@@ -68,16 +34,13 @@
// If an user implements its own ObjectAdapter, notification corresponding to data
// updates can be batched e.g. remove, add might be followed by notifyRemove, notifyAdd.
// But underlying data would have changed during the notifyRemove call by the previous add
- // operation. To handle this case, we enqueue the updates in a queue and have a worker
- // service that queue. The common case will be to have a single pending update in the queue.
- // But in case the worker encounters multiple updates in the queue, it will send a
- // notifyChanged() call to RecyclerView forcing it to do a full refresh.
+ // operation. To handle this case, we use QueueBasedDataObserver which forces
+ // recyclerview to do a full data refresh after each update operation.
if ((adapter instanceof ArrayObjectAdapter)
|| (adapter instanceof CursorObjectAdapter)
|| (adapter instanceof SparseArrayObjectAdapter)) {
mAdapter.registerObserver(new SimpleDataObserver());
} else {
- mHandler = new Handler();
mAdapter.registerObserver(new QueueBasedDataObserver());
}
}
@@ -177,46 +140,34 @@
}
}
+
+ /**
+ * When using custom {@link ObjectAdapter}, it's possible that the user may make multiple
+ * changes to the underlying data at once. The notifications about those updates may be
+ * batched and the underlying data would have changed to reflect latest updates as opposed
+ * to intermediate changes. In order to force RecyclerView to refresh the view with access
+ * only to the final data, we call notifyChange().
+ */
private class QueueBasedDataObserver extends SimpleDataObserver {
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
- incrementAndPost();
- super.onItemRangeChanged(positionStart, itemCount);
+ notifyChanged();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
- incrementAndPost();
- super.onItemRangeInserted(positionStart, itemCount);
+ notifyChanged();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
- incrementAndPost();
- super.onItemRangeRemoved(positionStart, itemCount);
+ notifyChanged();
}
@Override
public void onChanged() {
- incrementAndPost();
- super.onChanged();
- }
-
- @Override
- protected void onEventFired(
- final int eventType, final int positionStart, final int itemCount) {
-
- if (mPendingUpdateCount == 1) {
- mPendingUpdate = new Update(eventType, positionStart, itemCount);
- }
- }
-
- private void incrementAndPost() {
- mPendingUpdateCount++;
- if (mPendingUpdateCount == 1) {
- mHandler.post(notificationTask);
- }
+ notifyChanged();
}
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ArrayObjectAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/ArrayObjectAdapter.java
index 8133d33..68190d4 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ArrayObjectAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ArrayObjectAdapter.java
@@ -182,4 +182,9 @@
public <E> List<E> unmodifiableList() {
return Collections.unmodifiableList((List<E>) mItems);
}
+
+ @Override
+ public boolean isImmediateNotifySupported() {
+ return true;
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/CursorObjectAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/CursorObjectAdapter.java
index 620659d..483f3fb 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/CursorObjectAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/CursorObjectAdapter.java
@@ -184,4 +184,9 @@
invalidateCache(index);
}
}
+
+ @Override
+ public boolean isImmediateNotifySupported() {
+ return true;
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ObjectAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/ObjectAdapter.java
index eb26672..c464814 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ObjectAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ObjectAdapter.java
@@ -247,4 +247,12 @@
public long getId(int position) {
return NO_ID;
}
+
+ /**
+ * Returns true if the adapter pairs each underlying data change with a call to notify and
+ * false otherwise.
+ */
+ public boolean isImmediateNotifySupported() {
+ return false;
+ }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/SparseArrayObjectAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/SparseArrayObjectAdapter.java
index 0e64800..c52fd92 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/SparseArrayObjectAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/SparseArrayObjectAdapter.java
@@ -123,4 +123,9 @@
public Object lookup(int key) {
return mItems.get(key);
}
+
+ @Override
+ public boolean isImmediateNotifySupported() {
+ return true;
+ }
}
\ No newline at end of file