Notify RecyclerView.Adapter of changes on RecyclerView managed frame.
Bug: 139320633
Test: Verified working correctly using demo app.
Change-Id: I19f9b3c3ab9e9e94a412720e10b74c900f8d4143
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/BandSelectionHelperTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/BandSelectionHelperTest.java
index bc0cbc98..3a9a886 100644
--- a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/BandSelectionHelperTest.java
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/BandSelectionHelperTest.java
@@ -24,6 +24,7 @@
import android.view.MotionEvent;
import androidx.annotation.NonNull;
+import androidx.core.util.Consumer;
import androidx.recyclerview.selection.GridModel.GridHost;
import androidx.recyclerview.selection.testing.TestAdapter;
import androidx.recyclerview.selection.testing.TestAutoScroller;
@@ -74,7 +75,13 @@
SelectionPredicates.createSelectAnything(),
StorageStrategy.createStringStorage());
- EventBridge.install(mAdapter, mTracker, mKeyProvider);
+ EventBridge.install(mAdapter, mTracker, mKeyProvider, new Consumer<Runnable>() {
+ @Override
+ public void accept(Runnable runnable) {
+ runnable.run();
+ }
+ });
+
FocusDelegate<String> focusDelegate = FocusDelegate.dummy();
mBandController = new BandSelectionHelper<String>(
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTrackerTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTrackerTest.java
index 8ed4db9..7470b51 100644
--- a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTrackerTest.java
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTrackerTest.java
@@ -25,6 +25,7 @@
import android.util.SparseBooleanArray;
import androidx.annotation.NonNull;
+import androidx.core.util.Consumer;
import androidx.recyclerview.selection.SelectionTracker.SelectionPredicate;
import androidx.recyclerview.selection.testing.Bundles;
import androidx.recyclerview.selection.testing.SelectionProbe;
@@ -89,7 +90,13 @@
mSelectionPredicate,
StorageStrategy.createStringStorage());
- EventBridge.install(mAdapter, mTracker, mKeyProvider);
+ EventBridge.install(
+ mAdapter, mTracker, mKeyProvider, new Consumer<Runnable>() {
+ @Override
+ public void accept(Runnable runnable) {
+ runnable.run();
+ }
+ });
mTracker.addObserver(mListener);
@@ -515,7 +522,13 @@
mSelectionPredicate,
StorageStrategy.createStringStorage());
- EventBridge.install(mAdapter, mTracker, mKeyProvider);
+ EventBridge.install(
+ mAdapter, mTracker, mKeyProvider, new Consumer<Runnable>() {
+ @Override
+ public void accept(Runnable runnable) {
+ runnable.run();
+ }
+ });
mTracker.addObserver(mListener);
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTracker_SingleSelectTest.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTracker_SingleSelectTest.java
index 6dac018..f47d65e 100644
--- a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTracker_SingleSelectTest.java
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/DefaultSelectionTracker_SingleSelectTest.java
@@ -48,7 +48,6 @@
keyProvider,
SelectionPredicates.createSelectSingleAnything(),
StorageStrategy.createStringStorage());
- EventBridge.install(mAdapter, mTracker, keyProvider);
mTracker.addObserver(mListener);
diff --git a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/SelectionTrackers.java b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/SelectionTrackers.java
index 32379bf..d76ce51 100644
--- a/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/SelectionTrackers.java
+++ b/recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/SelectionTrackers.java
@@ -16,6 +16,7 @@
package androidx.recyclerview.selection.testing;
+import androidx.annotation.NonNull;
import androidx.recyclerview.selection.DefaultSelectionTracker;
import androidx.recyclerview.selection.EventBridge;
import androidx.recyclerview.selection.ItemKeyProvider;
@@ -37,7 +38,7 @@
SelectionPredicates.createSelectAnything(),
StorageStrategy.createStringStorage());
- EventBridge.install(adapter, tracker, keyProvider);
+ EventBridge.install(adapter, tracker, keyProvider, SelectionTrackers::runImmediately);
return tracker;
}
@@ -52,8 +53,13 @@
SelectionPredicates.createSelectAnything(),
StorageStrategy.createLongStorage());
- EventBridge.install(adapter, tracker, keyProvider);
+ EventBridge.install(adapter, tracker, keyProvider, SelectionTrackers::runImmediately);
return tracker;
}
+
+ // Test stand-in for RecyclerView::postOnAnimation.
+ private static void runImmediately(@NonNull Runnable runnable) {
+ runnable.run();
+ }
}
diff --git a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBridge.java b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBridge.java
index c273106..3ea5fb4 100644
--- a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBridge.java
+++ b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/EventBridge.java
@@ -26,6 +26,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
+import androidx.core.util.Consumer;
import androidx.recyclerview.widget.RecyclerView;
/**
@@ -50,37 +51,45 @@
* @param adapter
* @param selectionTracker
* @param keyProvider
+ * @param runner Callback allowing operation to be run at next opportune time.
+ * Implementation could be {@link RecyclerView#postOnAnimation(Runnable)}.
*
* @param <K> Selection key type. @see {@link StorageStrategy} for supported types.
*/
public static <K> void install(
@NonNull RecyclerView.Adapter<?> adapter,
@NonNull SelectionTracker<K> selectionTracker,
- @NonNull ItemKeyProvider<K> keyProvider) {
+ @NonNull ItemKeyProvider<K> keyProvider,
+ @NonNull Consumer<Runnable> runner) {
// setup bridges to relay selection and adapter events
- new TrackerToAdapterBridge<>(selectionTracker, keyProvider, adapter);
+ new TrackerToAdapterBridge<>(selectionTracker, keyProvider, adapter, runner);
adapter.registerAdapterDataObserver(selectionTracker.getAdapterDataObserver());
}
private static final class TrackerToAdapterBridge<K>
extends SelectionTracker.SelectionObserver<K> {
+ // Non-private as necessary to avoid synthetic accessors for inner classes.
+ final RecyclerView.Adapter<?> mAdapter;
private final ItemKeyProvider<K> mKeyProvider;
- private final RecyclerView.Adapter<?> mAdapter;
+ private final Consumer<Runnable> mRunner;
TrackerToAdapterBridge(
@NonNull SelectionTracker<K> selectionTracker,
@NonNull ItemKeyProvider<K> keyProvider,
- @NonNull RecyclerView.Adapter<?> adapter) {
+ @NonNull RecyclerView.Adapter<?> adapter,
+ Consumer<Runnable> runner) {
selectionTracker.addObserver(this);
checkArgument(keyProvider != null);
checkArgument(adapter != null);
+ checkArgument(runner != null);
mKeyProvider = keyProvider;
mAdapter = adapter;
+ mRunner = runner;
}
/**
@@ -96,7 +105,12 @@
return;
}
- mAdapter.notifyItemChanged(position, SelectionTracker.SELECTION_CHANGED_MARKER);
+ mRunner.accept(new Runnable() {
+ @Override
+ public void run() {
+ mAdapter.notifyItemChanged(position, SelectionTracker.SELECTION_CHANGED_MARKER);
+ }
+ });
}
}
diff --git a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
index 50cc4ceb..f913efd 100644
--- a/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
+++ b/recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
@@ -709,7 +709,7 @@
// Event glue between RecyclerView and SelectionTracker keeps the classes separate
// so that a SelectionTracker can be shared across RecyclerView instances that
// represent the same data in different ways.
- EventBridge.install(mAdapter, tracker, mKeyProvider);
+ EventBridge.install(mAdapter, tracker, mKeyProvider, mRecyclerView::post);
// Scroller is stateful and can be reset, but we don't manage it directly.
// GestureSelectionHelper will reset scroller when it is reset.