Fixed
Status Update
Comments
il...@google.com <il...@google.com>
cl...@google.com <cl...@google.com>
ap...@google.com <ap...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-master-dev
commit fb1c82582399043b149eb2630f524c75de9c88dc
Author: Jelle Fresen <jellefresen@google.com>
Date: Thu Aug 15 11:34:36 2019
Disallow intercept, touch slop and canScroll in nestedPreScroll
* Disallow intercept (requestDisallowInterceptTouchEvent(true))
When scroll delta is consumed by dispatchNestedPreScroll, the parent
should be requested not to intercept subsequent touch events, just as
when scroll is consumed by the widget itself or dispatchNestedScroll.
* Touch slop
NestedScrollingChild implementations should only call
dispatchNestedPreScroll after the delta x/y has exceeded the touch slop.
* canScroll (canScrollHorizontally/canScrollVertically)
The dx/dy values passed to dispatchNestedPreScroll should be zero if the
child can't scroll in that direction.
Fixed in:
- RecyclerView
- NestedScrollView
Bug: 138668210
Bug: 139530818
Test: ./gradlew connectedCheck
Change-Id: I85b327ad096fbbd204adb92f630770ec7fad5990
M core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingChildTest.java
M core/core/src/main/java/androidx/core/widget/NestedScrollView.java
M recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrolling3RequestDisallowInterceptTouchTest.java
M recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingChildTest.java
M recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
https://android-review.googlesource.com/1105373
https://goto.google.com/android-sha1/fb1c82582399043b149eb2630f524c75de9c88dc
Branch: androidx-master-dev
commit fb1c82582399043b149eb2630f524c75de9c88dc
Author: Jelle Fresen <jellefresen@google.com>
Date: Thu Aug 15 11:34:36 2019
Disallow intercept, touch slop and canScroll in nestedPreScroll
* Disallow intercept (requestDisallowInterceptTouchEvent(true))
When scroll delta is consumed by dispatchNestedPreScroll, the parent
should be requested not to intercept subsequent touch events, just as
when scroll is consumed by the widget itself or dispatchNestedScroll.
* Touch slop
NestedScrollingChild implementations should only call
dispatchNestedPreScroll after the delta x/y has exceeded the touch slop.
* canScroll (canScrollHorizontally/canScrollVertically)
The dx/dy values passed to dispatchNestedPreScroll should be zero if the
child can't scroll in that direction.
Fixed in:
- RecyclerView
- NestedScrollView
Bug: 138668210
Bug: 139530818
Test: ./gradlew connectedCheck
Change-Id: I85b327ad096fbbd204adb92f630770ec7fad5990
M core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingChildTest.java
M core/core/src/main/java/androidx/core/widget/NestedScrollView.java
M recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrolling3RequestDisallowInterceptTouchTest.java
M recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingChildTest.java
M recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
fa...@hotmail.com <fa...@hotmail.com> #3
Is
Description
Version used: 2.1.0-alpha01
Devices/Android versions reproduced on: API 28 emulator, Chrome OS
MediatorLiveData.addSource doesn't manually check for null source argument (annotation is there, which is good)
It's possible to accidentally add a null (or not yet initialized) source.
The issue is buried until the MediatorLiveData is observed, making it hard to find the original issue.
Best solution would be a quick check of the variables and fast fail before processing. e.g. assertNotNull(source)
- Sample project attached
relevant code:
private val mediatorLiveData = MediatorLiveData<Int>().apply {
// Here is the mistake, (allowed at compile time).
addSource(dataSource) { value = (it ?: 0) + 1 }
}
private val dataSource = MutableLiveData<Int>()
// This triggers the exception
mediatorLiveData.observe(this, Observer { // process })
Error output without check: (unhelpful unless you know the internals of MediatorLiveData)
2019-01-18 10:58:39.891 6385-6385/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.google.example.mediatorlatecheck, PID: 6385
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observeForever(androidx.lifecycle.Observer)' on a null object reference
at androidx.lifecycle.MediatorLiveData$Source.plug(MediatorLiveData.java:141)
at androidx.lifecycle.MediatorLiveData.onActive(MediatorLiveData.java:118)
at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:436)
at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:394)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:355)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:293)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:333)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:138)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:124)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:123)
at androidx.lifecycle.ReportFragment.onStart(ReportFragment.java:83)
at android.app.Fragment.performStart(Fragment.java:2548)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1334)
at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1576)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1637)
at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3046)
at android.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:3003)
at android.app.FragmentController.dispatchStart(FragmentController.java:193)
at android.app.Activity.performStart(Activity.java:7165)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2937)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)