Fixed
Status Update
Comments
se...@google.com <se...@google.com> #2
Hmm maybe. I would need that lambda to run before the updates are dispatched to the RV adapter because (conforming to this example) I'm using the title inside the RV items.
My actual example is here:https://github.com/JakeWharton/SdkSearch/blob/35ecf5c5c17edd60da3498eb38eab13786623548/frontend/android/src/main/java/com/jakewharton/sdksearch/ui/ItemAdapter.kt
I have a query term and a list of results. The view holders bold the query term inside the result. Not sure how common it is to use non-list data inside the list items like this. I could make a composite object of query+item and have a list of those, I suppose...
My actual example is here:
I have a query term and a list of results. The view holders bold the query term inside the result. Not sure how common it is to use non-list data inside the list items like this. I could make a composite object of query+item and have a list of those, I suppose...
se...@google.com <se...@google.com> #3
I think running the lambda first is very reasonable.
I'm assuming we'll still need to run those lambdas in the rare case a diff is dropped when too many lists are pushed. Would be nice to avoid any extra bind work (e.g. in the setTitle) case, but it would be surprising to have some of those lambdas never run.
I'm assuming we'll still need to run those lambdas in the rare case a diff is dropped when too many lists are pushed. Would be nice to avoid any extra bind work (e.g. in the setTitle) case, but it would be surprising to have some of those lambdas never run.
yb...@google.com <yb...@google.com> #4
The problem with running the lambda first is that you can't touch the RecyclerView state in many ways, e.g. asking it to scroll to specific content.
May want to differentiate between pre-swap and post swap callbacks.
May want to differentiate between pre-swap and post swap callbacks.
se...@google.com <se...@google.com> #5
When talking about when to run the lambda, I entirely forgot - RecyclerView update notifications (e.g. from DiffUtil.Result or Adapter.notifyItem*) are always deferred.
RecyclerView posts before doing any bind work after dispatching any sort of notifyItem*** signals to coalesce changes. This means it's safe to update data you'll display in the callback, even if it's dispatched after the swap. See triggerUpdateProcessor -https://cs.corp.google.com/android/frameworks/base/core/java/com/android/internal/widget/RecyclerView.java?q=triggerUpdateProcessor&sq=package:%5Eandroid$&g=0&l=4919
I added the requested API, and just have it running after the swap. Also manually verified callback can be used to update adapter state displayed.
Fixed withhttps://android-review.googlesource.com/c/platform/frameworks/support/+/730779 - will go out with next feature release (Paging 2.1)
RecyclerView posts before doing any bind work after dispatching any sort of notifyItem*** signals to coalesce changes. This means it's safe to update data you'll display in the callback, even if it's dispatched after the swap. See triggerUpdateProcessor -
I added the requested API, and just have it running after the swap. Also manually verified callback can be used to update adapter state displayed.
Fixed with
ch...@beyls.net <ch...@beyls.net> #6
Released with Paging 2.1.0-alpha01
ne...@gmail.com <ne...@gmail.com> #7
I think the real problem is that LiveData has no callback to know that no one wants it anymore; like onReset in Loader.
So there's 2 options for database observers:
1. It either has to un-register observer in onInactive and on next onActive re-query db. Problematic is if nothing has changed you have to filter values or dispatch unnecessarily, and you'll pay the price of query which could be expensive.
2. Register weak observer, or have wear ref to LiveData
Room uses option 2. I created my own LiveData and I used the same (https://bitbucket.org/snippets/Boza-s6/xe8749/sample-livedata-with-features-like-loaders#EmailContentLiveData.java-104 ), because it was obvious solution, but now I see it will not work in every possible case.
I think there should be statically referenced Lifecycle object to which LiveData subscribes when using observeForever() (and observer is anonymous class, maybe?).
So there's 2 options for database observers:
1. It either has to un-register observer in onInactive and on next onActive re-query db. Problematic is if nothing has changed you have to filter values or dispatch unnecessarily, and you'll pay the price of query which could be expensive.
2. Register weak observer, or have wear ref to LiveData
Room uses option 2. I created my own LiveData and I used the same (
I think there should be statically referenced Lifecycle object to which LiveData subscribes when using observeForever() (and observer is anonymous class, maybe?).
m....@gmail.com <m....@gmail.com> #8
I ran into the same problem yesterday. It tooked me hours to understand what is happening and why my observeForever-observer suddenly stopped being invoked.
I think it is a really bad design that someone should know the implementation details of generated Room DB Code.
I want to use observerForever the same way like i use the simple observe and dont want to ran into problems because of internal implementation details.
I think it is a really bad design that someone should know the implementation details of generated Room DB Code.
I want to use observerForever the same way like i use the simple observe and dont want to ran into problems because of internal implementation details.
yb...@google.com <yb...@google.com>
yb...@google.com <yb...@google.com>
ap...@google.com <ap...@google.com> #9
Project: platform/frameworks/support
Branch: androidx-master-dev
commit bab31cacd4ae98057b694f6ae4c781f5f25ee0c9
Author: Yigit Boyar <yboyar@google.com>
Date: Wed Oct 31 23:41:00 2018
Fix live data observe forever in room
This CL fixes a problem where if DAO returned LiveData is
observed with observeForever but there are no references
to the LiveData, it would eventually be garbage collected.
To avoid this, InvalidationTracker now manages these LiveData
objects and strongly references them as long as there is an
active observer.
To be 100%, we should actually do it when LiveData has observers
but right now that API does not exist in the LiveData side
to get notified when the observer count changes 0 and 1.
I've also cleaned up some test code to avoid duplicating the
test observers in each test.
I've also added an integration test that uses room w/o any of
the optional dependencies to ensure that we don't break the
contract on compileOnly dependencies.
Bug: 74477406
Test: LiveDataQueryTest, InvalidationTrackerTest, NoAppCompatTestApp
Change-Id: If88114306d7e20ddaed0312a1203a0d14b710145
M arch/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/LiveDataQueryResultBinder.kt
M room/compiler/src/test/data/daoWriter/output/ComplexDao.java
A room/integration-tests/noappcompattestapp/.gitignore
A room/integration-tests/noappcompattestapp/README.md
A room/integration-tests/noappcompattestapp/build.gradle
A room/integration-tests/noappcompattestapp/src/androidTest/java/androidx/room/integration/noappcompat/BareDatabaseTest.java
A room/integration-tests/noappcompattestapp/src/main/AndroidManifest.xml
A room/integration-tests/noappcompattestapp/src/main/java/androidx/room/integration/noappcompat/BareDatabase.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTrackerTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestLifecycleOwner.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestObserver.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestUtil.java
M room/runtime/build.gradle
A room/runtime/src/main/java/androidx/room/InvalidationLiveDataContainer.java
M room/runtime/src/main/java/androidx/room/InvalidationTracker.java
A room/runtime/src/main/java/androidx/room/RoomTrackingLiveData.java
A room/runtime/src/test/java/androidx/room/InvalidationLiveDataContainerTest.kt
M room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
M settings.gradle
https://android-review.googlesource.com/810053
https://goto.google.com/android-sha1/bab31cacd4ae98057b694f6ae4c781f5f25ee0c9
Branch: androidx-master-dev
commit bab31cacd4ae98057b694f6ae4c781f5f25ee0c9
Author: Yigit Boyar <yboyar@google.com>
Date: Wed Oct 31 23:41:00 2018
Fix live data observe forever in room
This CL fixes a problem where if DAO returned LiveData is
observed with observeForever but there are no references
to the LiveData, it would eventually be garbage collected.
To avoid this, InvalidationTracker now manages these LiveData
objects and strongly references them as long as there is an
active observer.
To be 100%, we should actually do it when LiveData has observers
but right now that API does not exist in the LiveData side
to get notified when the observer count changes 0 and 1.
I've also cleaned up some test code to avoid duplicating the
test observers in each test.
I've also added an integration test that uses room w/o any of
the optional dependencies to ensure that we don't break the
contract on compileOnly dependencies.
Bug: 74477406
Test: LiveDataQueryTest, InvalidationTrackerTest, NoAppCompatTestApp
Change-Id: If88114306d7e20ddaed0312a1203a0d14b710145
M arch/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/LiveDataQueryResultBinder.kt
M room/compiler/src/test/data/daoWriter/output/ComplexDao.java
A room/integration-tests/noappcompattestapp/.gitignore
A room/integration-tests/noappcompattestapp/README.md
A room/integration-tests/noappcompattestapp/build.gradle
A room/integration-tests/noappcompattestapp/src/androidTest/java/androidx/room/integration/noappcompat/BareDatabaseTest.java
A room/integration-tests/noappcompattestapp/src/main/AndroidManifest.xml
A room/integration-tests/noappcompattestapp/src/main/java/androidx/room/integration/noappcompat/BareDatabase.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTrackerTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestLifecycleOwner.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestObserver.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestUtil.java
M room/runtime/build.gradle
A room/runtime/src/main/java/androidx/room/InvalidationLiveDataContainer.java
M room/runtime/src/main/java/androidx/room/InvalidationTracker.java
A room/runtime/src/main/java/androidx/room/RoomTrackingLiveData.java
A room/runtime/src/test/java/androidx/room/InvalidationLiveDataContainerTest.kt
M room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
M settings.gradle
yb...@google.com <yb...@google.com>
yb...@google.com <yb...@google.com> #10
FYI this requires client to update to Room 2.1.0-alpha03 but it is fully compatible with 1.x that WM uses.
yb...@google.com <yb...@google.com> #11
actually it won't work because the change is in generated code. I'll try to backport itinto WM.
ap...@google.com <ap...@google.com> #13
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 3fb46bd8602faaf9c34aa969f8ae589c251c2f72
Author: Yigit Boyar <yboyar@google.com>
Date: Fri Nov 30 13:19:34 2018
Track LiveData returned by the WM
This CL works around a bug in Room 1.x where LiveData returned
by Room might be garbage collected.
Now work manager tracks any live data it returns as long as the
LiveData is active.
Bug: 74477406
Test: ObserForeverTest, WorkManagerLiveDataTrackerTest
Change-Id: I1e45dade1e8a3c29d6c35f7cb0c6e072c68ee658
A work/workmanager/src/androidTest/java/androidx/work/impl/ObserveForeverTest.java
M work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
A work/workmanager/src/main/java/androidx/work/impl/WorkManagerLiveDataTracker.java
A work/workmanager/src/test/java/androidx/work/impl/WorkManagerLiveDataTrackerTest.java
https://android-review.googlesource.com/838833
https://goto.google.com/android-sha1/3fb46bd8602faaf9c34aa969f8ae589c251c2f72
Branch: androidx-master-dev
commit 3fb46bd8602faaf9c34aa969f8ae589c251c2f72
Author: Yigit Boyar <yboyar@google.com>
Date: Fri Nov 30 13:19:34 2018
Track LiveData returned by the WM
This CL works around a bug in Room 1.x where LiveData returned
by Room might be garbage collected.
Now work manager tracks any live data it returns as long as the
LiveData is active.
Bug: 74477406
Test: ObserForeverTest, WorkManagerLiveDataTrackerTest
Change-Id: I1e45dade1e8a3c29d6c35f7cb0c6e072c68ee658
A work/workmanager/src/androidTest/java/androidx/work/impl/ObserveForeverTest.java
M work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
A work/workmanager/src/main/java/androidx/work/impl/WorkManagerLiveDataTracker.java
A work/workmanager/src/test/java/androidx/work/impl/WorkManagerLiveDataTrackerTest.java
Description
repro steps from the developer:
launch the app on a device, press the button to update the counters. Then after you use "force gc" from android monitor, the second counter will stop updating
Looks like because nothing keeps a reference to the AlwaysOnLifecycle or the LiveData, both end up being GC'ed. Before it was a single instance so it didn't get GC'ed.
We probably need to keep AlwaysOnLifecycle in memory as long as it has an observer.