Fixed
Status Update
Comments
ta...@gmail.com <ta...@gmail.com> #2
(Copying my comment from https://issuetracker.google.com/issues/73976255#comment21 )
The onLoaderReset problem makes working with CursorLoader and CursorAdapter suddenly very cumbersome in 27.1.0.
In order to avoid the "empty data" period of time after onLoaderReset, my extremely hacky workaround is to create a second identical loader, with a separate Loader ID, and flip between the two Loaders with each call to restartLoader, so that the previous Cursor remains alive until the next onLoadFinished callback.
The onLoaderReset problem makes working with CursorLoader and CursorAdapter suddenly very cumbersome in 27.1.0.
In order to avoid the "empty data" period of time after onLoaderReset, my extremely hacky workaround is to create a second identical loader, with a separate Loader ID, and flip between the two Loaders with each call to restartLoader, so that the previous Cursor remains alive until the next onLoadFinished callback.
il...@google.com <il...@google.com>
to...@gmail.com <to...@gmail.com> #3
Can you confirm this is unwanted change or not?
If it's wanted I'll probably have to priorize my migration to normal ViewModel/LiveData.
If it's wanted I'll probably have to priorize my migration to normal ViewModel/LiveData.
il...@google.com <il...@google.com> #4
Yes, this is an unintentional regression.
A better workaround is to:
1) Add a Loader field (say, mLoader) to your FragmentActivity/Fragment
2) Where you used to call restartLoader(), replace with:
mLoader = null;
mLoader = loaderManager.restartLoader(ID, bundle, callbacks);
3) For onLoaderReset(), use this pattern:
if (loader == mLoader) {
// Your existing reset logic
}
4) If you use initLoader(), make sure to assign its return value to mLoader
5) If you use destroyLoader(), make sure to null out mLoader after the call to destroyLoader()
A better workaround is to:
1) Add a Loader field (say, mLoader) to your FragmentActivity/Fragment
2) Where you used to call restartLoader(), replace with:
mLoader = null;
mLoader = loaderManager.restartLoader(ID, bundle, callbacks);
3) For onLoaderReset(), use this pattern:
if (loader == mLoader) {
// Your existing reset logic
}
4) If you use initLoader(), make sure to assign its return value to mLoader
5) If you use destroyLoader(), make sure to null out mLoader after the call to destroyLoader()
ta...@gmail.com <ta...@gmail.com> #5
Re: #4: I don't think that's a perfect workaround. I had tried a similar workaround, setting a flag to skip a swapCursor() onLoaderReset the first time after restartLoader. This broke when calling restartLoader() multiple times quickly, for example in response to characters typed on a keyboard. I got StaleDataException from the CursorAdapter trying to use the old Cursor.
il...@google.com <il...@google.com> #6
Ah, yes that fixes the issue on the CursorAdapter side, but CursorLoader still closes the Cursor in onReset(), of which there's no good workaround for.
il...@google.com <il...@google.com> #7
This has been fixed and will be available in future Support Library releases. When a Loader is replaced with restartLoader(), the existing Loader won't be reset() until the replacement Loader returns data - this ensures that resources remain valid. When using restartLoader(), the previous LoaderCallbacks won't get a callback to onLoaderReset() - this ensures that your UI (such as a CursorAdapter) is not cleared.
vo...@gmail.com <vo...@gmail.com> #8
Any ET on hotfix release date for 27.1x?
kk...@google.com <kk...@google.com> #9
This bug has been fixed in Support Library 27.1.1.
ku...@gmail.com <ku...@gmail.com> #10
Racave varjan
ku...@gmail.com <ku...@gmail.com> #11
Racave varjan
ku...@gmail.com <ku...@gmail.com> #12
Racave varjan
gs...@gmail.com <gs...@gmail.com> #13
Mise a jour
Description
Callback order is changed when calling restartLoader.
The documentation of restartLoader Says: "If a loader with the same id has previously been started it will automatically be destroyed when the new loader completes its work. The callback will be delivered before the old loader is destroyed."
But new implementation does not that at all. It calls onLoaderReset then onCreateLoader then onLoadFinished. (Previous implementation was sometimes broken and never called onLoaderReset but at least there was no long duration where we have no data to display).
This is a major change because this means you can't keep the previous data during the load as it's invalidated but you have nothing to display since the new loader is not finished. Meaning empty screen on reload = quite bad UX.