Status Update
Comments
ki...@google.com <ki...@google.com>
da...@gmail.com <da...@gmail.com> #2
I believe that this is following on from
In the linked thread it is suggested that withOnItemActivatedListener
can be used to correctly handle click events on the view. I've had a look through the sample project
For my use-case I would like a reference to the view in the ViewHolder for shared element transitions - setting on onClickListener in the ViewHolder made this easy. I'll have to work around by finding the view holder with the motion event for now.
I think it should be clearer in the version release notes that this behaviour change is present.
sh...@google.com <sh...@google.com>
sm...@google.com <sm...@google.com> #3
ki...@gmail.com <ki...@gmail.com> #4
But your response sounds like you're focusing on that one and consider the second point a non-issue, just because it was already present in 1.0?
Please note that it does not only affect custom OnClickListeners, but also standard widgets like checkboxes. If you click through items (read: click on the items' checkboxes) slowly after activating selection mode, you will only select/unselect further items. If you click faster, selection will skip some items and instead toggle the checkbox. And as I said, even without interactive items, selection just feels utterly sluggish when it skips user clicks. The whole user experience is far, far away from the "good old" list view.
Offtopic: Those new androidx/jetpack libraries don't feel like they're pretty well geared to each other. Combining RecyclerView and SelectionTracker with ItemTouchHelper opens another issue. When using a drag handle within a selectable list item, clicking the handle and starting to move the item slowly will select the item and start selection mode while drag mode is active. It gives weird user experience and requires lots of workarounds to come to a sane "standard" behaviour.
sm...@google.com <sm...@google.com> #5
The second issue you describe is tracked by 159025478.
The last issue you described is likely related to 139141511.
ki...@gmail.com <ki...@gmail.com> #6
sm...@google.com <sm...@google.com> #7
Just be advised that the issues are being tracked.
...478 > Replace use of GestureDetector with custom event detection
...511 > Handle onRequestDisallowInterceptTouchEvent correctly
sm...@google.com <sm...@google.com> #8
Separately I landed a fix to comply with onRequestDisallowInterceptTouchEvent requests. This will appear in 1.1.0-rc02. Fancy demo app was updated with "swipe away" supporting using ItemTouchHelper to demonstrate compliance.
sm...@google.com <sm...@google.com> #9
That said, there are still cases where OnClickListeners added to child views are being called (at least using the Fancy demo activity).
1) Long press on an existing selected item.
2) When making many multi-taps (whacking the screen repeatedly with multiple fingers).
In both of those cases I haven't been able to track down a cause, but have verified that *when* TouchInputHandler receives events, it handles them correctly. It doesn't rule out issues elsewhere in the library, but I don't see any obvious paths of investigation. <Steve glares directly at GestureDetector once again>.
sm...@google.com <sm...@google.com> #10
I'd like to update the docs to provide some guidance, but am not sure where would be most effective.
ap...@google.com <ap...@google.com> #11
Branch: androidx-master-dev
commit 801fbf8d34a6c5b3939932c0b143b55e3ef1859b
Author: Steve McKay <smckay@google.com>
Date: Fri Aug 14 16:46:52 2020
Fix an issue where TouchInputHandler misinterpreted events from GestureDetector.
Consume up events from double tap stream, ignore double tap event iteself.
Bug: 161162268
Test: Added coverage to TouchInputHandler.
Change-Id: Ib0293818216d1c388e49860e976b639742838784
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestDragListener.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemActivatedListener.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/DemoItemHolder.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancySelectionDemoActivity.java
sm...@google.com <sm...@google.com> #12
Unfortunately I don't have a fix the issue of child View onClickHandlers firing at this time and will retain this bug to track the issue.
ap...@google.com <ap...@google.com> #14
Branch: snap-temp-L55000000669795486
commit a74207a20aa7a3b1ccd381654d7d34cc7c8bbb65
Author: Steve McKay <smckay@google.com>
Date: Fri Aug 14 16:46:52 2020
Fix an issue where TouchInputHandler misinterpreted events from GestureDetector.
Consume up events from double tap stream, ignore double tap event iteself.
Bug: 161162268
Test: Added coverage to TouchInputHandler.
Change-Id: Ib0293818216d1c388e49860e976b639742838784
(cherry picked from commit 18714872d72e6771c4c25ab856a0f42c253aec16)
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestDragListener.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemActivatedListener.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancyItemHolder.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancySelectionDemoActivity.java
ap...@google.com <ap...@google.com> #15
Branch: snap-temp-L13100000669799324
commit f895c3b8a820c0fdfa185f4a2839f68f6aa9277b
Author: Steve McKay <smckay@google.com>
Date: Fri Aug 14 16:46:52 2020
Fix an issue where TouchInputHandler misinterpreted events from GestureDetector.
Consume up events from double tap stream, ignore double tap event iteself.
Bug: 161162268
Test: Added coverage to TouchInputHandler.
Change-Id: Ib0293818216d1c388e49860e976b639742838784
(cherry picked from commit 18714872d72e6771c4c25ab856a0f42c253aec16)
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestDragListener.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemActivatedListener.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancyItemHolder.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancySelectionDemoActivity.java
ap...@google.com <ap...@google.com> #16
Branch: snap-temp-L10500000669872246
commit 8b88b0468be7955e2f7075f4ee2efe8d137172a8
Author: Steve McKay <smckay@google.com>
Date: Fri Aug 14 16:46:52 2020
Fix an issue where TouchInputHandler misinterpreted events from GestureDetector.
Consume up events from double tap stream, ignore double tap event iteself.
Bug: 161162268
Test: Added coverage to TouchInputHandler.
Change-Id: Ib0293818216d1c388e49860e976b639742838784
(cherry picked from commit 18714872d72e6771c4c25ab856a0f42c253aec16)
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestDragListener.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemActivatedListener.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancyItemHolder.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancySelectionDemoActivity.java
ap...@google.com <ap...@google.com> #17
Branch: snap-temp-L85700000669873256
commit e02c8fe7e4dbb69015b0e702ed4a58995d8cd6aa
Author: Steve McKay <smckay@google.com>
Date: Fri Aug 14 16:46:52 2020
Fix an issue where TouchInputHandler misinterpreted events from GestureDetector.
Consume up events from double tap stream, ignore double tap event iteself.
Bug: 161162268
Test: Added coverage to TouchInputHandler.
Change-Id: Ib0293818216d1c388e49860e976b639742838784
(cherry picked from commit 18714872d72e6771c4c25ab856a0f42c253aec16)
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestDragListener.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemActivatedListener.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancyItemHolder.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancySelectionDemoActivity.java
ap...@google.com <ap...@google.com> #18
Branch: snap-temp-L23500000669881336
commit 16f23c952eb7cbc57c2010f36006b4a2e32206d0
Author: Steve McKay <smckay@google.com>
Date: Fri Aug 14 16:46:52 2020
Fix an issue where TouchInputHandler misinterpreted events from GestureDetector.
Consume up events from double tap stream, ignore double tap event iteself.
Bug: 161162268
Test: Added coverage to TouchInputHandler.
Change-Id: Ib0293818216d1c388e49860e976b639742838784
(cherry picked from commit 18714872d72e6771c4c25ab856a0f42c253aec16)
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/TouchInputHandlerTest.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestDragListener.java
M recyclerview/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/testing/TestOnItemActivatedListener.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MouseInputHandler.java
M recyclerview/recyclerview-selection/src/main/java/androidx/recyclerview/selection/TouchInputHandler.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancyItemHolder.java
M samples/Support7Demos/src/main/java/com/example/android/supportv7/widget/selection/fancy/FancySelectionDemoActivity.java
an...@google.com <an...@google.com> #19
The following changes were cherrypicked through
Release Track:
Changes: aosp/1404332
sm...@google.com <sm...@google.com> #20
During testing, I did discover a few corner cases I believe are not regressions but relate to touch handling. I'll document those is separate bugs.
ki...@gmail.com <ki...@gmail.com> #22
Invoke-customs are only supported starting with Android O (--min-api 26)
Stack trace:
com.android.tools.r8.a: Invoke-customs are only supported starting with Android O (--min-api 26)
at com.android.tools.r8.dex.r.a(:291)
at com.android.tools.r8.dex.r.a(:98)
at com.android.tools.r8.dex.r.b(:188)
at com.android.tools.r8.dex.b.a(:63)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:125)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:69)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
at com.google.common.util.concurrent.MoreExecutors$DirectExecutorService.execute(MoreExecutors.java:322)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:66)
at com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:36)
at com.android.tools.r8.dex.b.b(:46)
at com.android.tools.r8.D8.d(:92)
at com.android.tools.r8.D8.b(:1)
at com.android.tools.r8.utils.W.a(:30)
at com.android.tools.r8.D8.run(:11)
at com.android.builder.dexing.D8DexArchiveBuilder.convert(D8DexArchiveBuilder.java:116)
at com.android.build.gradle.internal.dependency.BaseDexingTransform.process(DexingTransform.kt:296)
at com.android.build.gradle.internal.dependency.BaseDexingTransform.processNonIncrementally(DexingTransform.kt:243)
at com.android.build.gradle.internal.dependency.BaseDexingTransform.doTransform(DexingTransform.kt:153)
at com.android.build.gradle.internal.dependency.BaseDexingTransform.access$doTransform(DexingTransform.kt:69)
at com.android.build.gradle.internal.dependency.BaseDexingTransform$transform$1.invoke(DexingTransform.kt:104)
at com.android.build.gradle.internal.dependency.BaseDexingTransform$transform$1.invoke(DexingTransform.kt:69)
at com.android.build.gradle.internal.tasks.BlocksUtilsKt.recordArtifactTransformSpan(BlocksUtils.kt:33)
at com.android.build.gradle.internal.dependency.BaseDexingTransform.transform(DexingTransform.kt:100)
at org.gradle.api.internal.artifacts.transform.DefaultTransformer.transform(DefaultTransformer.java:189)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory$TransformerExecution.execute(DefaultTransformerInvocationFactory.java:332)
at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$0(ExecuteStep.java:32)
at java.util.Optional.map(Optional.java:215)
at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:32)
at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:63)
at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:35)
at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49)
at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34)
at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43)
at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34)
at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44)
at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54)
at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38)
at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:153)
at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:67)
at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:41)
at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44)
at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33)
at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92)
at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85)
at java.util.Optional.map(Optional.java:215)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39)
at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76)
at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94)
at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49)
at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79)
at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78)
at java.util.Optional.orElseGet(Optional.java:267)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39)
at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40)
at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28)
at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory$2.lambda$call$2(DefaultTransformerInvocationFactory.java:200)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory.fireTransformListeners(DefaultTransformerInvocationFactory.java:269)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory.access$300(DefaultTransformerInvocationFactory.java:79)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory$2.call(DefaultTransformerInvocationFactory.java:178)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory$2.call(DefaultTransformerInvocationFactory.java:175)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory.lambda$doTransform$0(DefaultTransformerInvocationFactory.java:175)
at org.gradle.api.internal.artifacts.transform.ImmutableTransformationWorkspaceProvider.lambda$withWorkspace$0(ImmutableTransformationWorkspaceProvider.java:81)
at org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess.withFileLock(LockOnDemandCrossProcessCacheAccess.java:90)
at org.gradle.cache.internal.DefaultCacheAccess.withFileLock(DefaultCacheAccess.java:181)
at org.gradle.cache.internal.DefaultPersistentDirectoryStore.withFileLock(DefaultPersistentDirectoryStore.java:172)
at org.gradle.cache.internal.DefaultCacheFactory$ReferenceTrackingCache.withFileLock(DefaultCacheFactory.java:196)
at org.gradle.api.internal.artifacts.transform.ImmutableTransformationWorkspaceProvider.withWorkspace(ImmutableTransformationWorkspaceProvider.java:76)
at org.gradle.api.internal.artifacts.transform.AbstractCachingTransformationWorkspaceProvider.lambda$withWorkspace$0(AbstractCachingTransformationWorkspaceProvider.java:56)
at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4718)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3445)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2194)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2153)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2043)
at com.google.common.cache.LocalCache.get(LocalCache.java:3851)
at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4713)
at org.gradle.api.internal.artifacts.transform.AbstractCachingTransformationWorkspaceProvider.withWorkspace(AbstractCachingTransformationWorkspaceProvider.java:55)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory.doTransform(DefaultTransformerInvocationFactory.java:175)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory.access$000(DefaultTransformerInvocationFactory.java:79)
at org.gradle.api.internal.artifacts.transform.DefaultTransformerInvocationFactory$1.invoke(DefaultTransformerInvocationFactory.java:141)
at org.gradle.api.internal.artifacts.transform.CacheableInvocation$1.invoke(CacheableInvocation.java:58)
at org.gradle.api.internal.artifacts.transform.TransformationNode$ChainedTransformationNode$1.lambda$transform$0(TransformationNode.java:226)
at org.gradle.internal.Try$Success.flatMap(Try.java:157)
at org.gradle.api.internal.artifacts.transform.TransformationNode$ChainedTransformationNode$1.transform(TransformationNode.java:225)
at org.gradle.api.internal.artifacts.transform.TransformationNode$ArtifactTransformationStepBuildOperation.call(TransformationNode.java:267)
at org.gradle.api.internal.artifacts.transform.TransformationNode$ArtifactTransformationStepBuildOperation.call(TransformationNode.java:247)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
at org.gradle.api.internal.artifacts.transform.TransformationNode$ChainedTransformationNode.execute(TransformationNode.java:222)
at org.gradle.execution.plan.WorkNodeExecutor.execute(WorkNodeExecutor.java:27)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
at org.gradle.execution.plan.DefaultPlanExecutor.process(DefaultPlanExecutor.java:72)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph.executeWithServices(DefaultTaskExecutionGraph.java:189)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph.execute(DefaultTaskExecutionGraph.java:166)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:41)
at org.gradle.execution.DefaultBuildWorkExecutor.execute(DefaultBuildWorkExecutor.java:40)
at org.gradle.execution.DefaultBuildWorkExecutor.access$000(DefaultBuildWorkExecutor.java:24)
at org.gradle.execution.DefaultBuildWorkExecutor$1.proceed(DefaultBuildWorkExecutor.java:48)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:49)
at org.gradle.execution.DefaultBuildWorkExecutor.execute(DefaultBuildWorkExecutor.java:40)
at org.gradle.execution.DefaultBuildWorkExecutor.execute(DefaultBuildWorkExecutor.java:33)
at org.gradle.execution.IncludedBuildLifecycleBuildWorkExecutor.execute(IncludedBuildLifecycleBuildWorkExecutor.java:36)
at org.gradle.execution.DeprecateUndefinedBuildWorkExecutor.execute(DeprecateUndefinedBuildWorkExecutor.java:39)
at org.gradle.execution.BuildOperationFiringBuildWorkerExecutor$ExecuteTasks.run(BuildOperationFiringBuildWorkerExecutor.java:57)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
at org.gradle.execution.BuildOperationFiringBuildWorkerExecutor.execute(BuildOperationFiringBuildWorkerExecutor.java:42)
at org.gradle.initialization.DefaultGradleLauncher.runWork(DefaultGradleLauncher.java:244)
at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:154)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:130)
at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:110)
at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:60)
at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:57)
at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:85)
at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:78)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:78)
at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:57)
at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:54)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:63)
at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:51)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:45)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:80)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:60)
at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:38)
at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:68)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:27)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.lang.Thread.run(Thread.java:748)
Suppressed: java.util.concurrent.ExecutionException: com.android.tools.r8.a: Invoke-customs are only supported starting with Android O (--min-api 26)
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:552)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:513)
at com.google.common.util.concurrent.FluentFuture$TrustedFuture.get(FluentFuture.java:86)
at com.android.tools.r8.utils.U0.a(:14)
at com.android.tools.r8.dex.b.b(:101)
... 216 more
[CIRCULAR REFERENCE:com.android.tools.r8.a: Invoke-customs are only supported starting with Android O (--min-api 26)]
I have no idea what this means.
Did you drop API 25 support in rc02?
sm...@google.com <sm...@google.com> #23
The release doesn't contain any changes to target APIs or adopt any new SDK features. The AndroidX toolchain is quite rigorous in guarding against accident adoption of features. The library uses the AndroidX defaults: minSdk of 14 and source compatibility with Java 8.
I think this is the first release that actually employs a Java 8 feature, though. A function reference.
SelectionTracker:
> EventBridge.install(mAdapter, tracker, mKeyProvider, mRecyclerView::post);
So I'd check your project settings to see if you've enabled support for 1.8 language features.
Lemme know how it works out for you.
ki...@gmail.com <ki...@gmail.com> #24
Is that documented anywhere? The AndroidX introductory pages and the migration guide didn't note Java 8 source compatibility as a requirement.
I now added:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
It compiles fine and part 2 of this bug (fast clicking multiple items in a row) seems fixed. However, onClick() is still triggered after enabling selection with a long click. I can also confirm the bugs you disovered in
Thanks for investigating and fixing the bugs on "your" side of the library.
PS: I don't get the point of burying AndroidX bugs in Google's private trackers and linking to them here. The public bug tracker is becoming more and more useless, sorry.
sm...@google.com <sm...@google.com> #25
*Question*
This is repro-able in the original demo app you uploaded?
*Ask*
Would you mind trying to repro the problem with FancySelectionDemoActivity (from the AndroidX samples folder)? Each child view has an OnClickListener that turns the background dark. So it's jarringly obvious when OnClick is handled.
I'd like to figure this one out, because OnClick firing on initial selection would be a stable release blocker for me, but firing on an existing selection not so, since that would seem an uncommon action by users.
As to public vs private bugs. I'll make an effort to prioritize public issues over private issues. FWIW, I'm a part time contributor to AndroidX. I've been tracking my work using internal bugs, because
1) that's what is "normal" for me, and
2) I track prospective work ideas there that I don't want made public (because people will look at them as promises, which they aren't).
Does your comment on public vs private apply to other components or just RecyclerView-Selection? I'm happy to relay feedback if it applies to others.
ki...@gmail.com <ki...@gmail.com> #26
Can you attach an Android Studio project of FancySelectionDemoActivity?
sm...@google.com <sm...@google.com> #27
FancySelectionDemoActivity is accesible via SupportV7Demos
You can launch it directly from android studio, or it is accessible from the API Demo app under RecyclerView > Selection > "Gesture and Pointer (for Chromebooks!)"
ki...@gmail.com <ki...@gmail.com> #28
sm...@google.com <sm...@google.com> #29
I guess my hands are shakier than yours :)
I updated
Thanks again for helping out, your feedback is helpful and appreciated!
Description
Version used: 1.1.0-rc01
Theme used: Theme.AppCompat.Light.DarkActionBar
Devices/Android versions reproduced on: Motorola Moto G6, Android 9
When the item views of a RecyclerView have OnClickListeners attached, the behaviour of firing onClick events during selection is quite unpredictable. As soon as at least one item was selected, classic ListView did no longer fire any click events for individual list items until all items were unselected.
Current recyclerview-selection exhibits two behaviours I would consider a bug, but maybe I'm using the API in a wrong way:
1. When long-clicking an item to enable multi-item selection, the item is marked as selected/activated as expected. But as soon as you release the finger, an onClick event will be triggered, despite the fact that RecyclerView is currently in selection mode. This behaviour is new since 1.1.0-rc01 and was not present in 1.0.0.
2. After enabling selection mode by long-clicking an item, you can select/activate other items by simply clicking on them. This works fine as long as you click through the items slowly. Then one by one gets selected and no onClick events get fired. But when you click a bit faster, every second item is not selected, but instead clicked (triggering onClick event). This problem existed in 1.0.0 and is still present in 1.1.0-rc01.
The following log shows a sequence of onItemStateChanged and onClick events triggered by long-clicking item 0 to enable selection, then clicking items 1, 2 and 3 quickly.
Expected result: Item 0 is selected, then items 1, 2 and 3 are selected, no onClicks get triggered.
Result on my device: Item 0 is selected, then onClick is triggered for item 0. Items 1 and 3 are selected and item 2 fires an onClick event in between.
click item 0 and hold button:
2020-07-13 21:55:01.402 15005-15005/com.example.recyclerviewdemo E/onItemStateChanged: 0: true
item 0 is selected, now release finger:
2020-07-13 21:55:02.306 15005-15005/com.example.recyclerviewdemo E/onClick: item 0
now click (and release) items 1, 2 and 3 quickly:
2020-07-13 21:55:06.850 15005-15005/com.example.recyclerviewdemo E/onItemStateChanged: 1: true
2020-07-13 21:55:07.038 15005-15005/com.example.recyclerviewdemo E/onClick: item 2
2020-07-13 21:55:07.236 15005-15005/com.example.recyclerviewdemo E/onItemStateChanged: 3: true
Attached is an Android Studio project to reproduce the behaviour.
Item IDs == item positions for brevity, the library behaves the same way in a more complex project with "real" item IDs and a custom key provider.