Fixed
Status Update
Comments
il...@google.com <il...@google.com>
il...@google.com <il...@google.com> #2
Able to reproduce the issue from your description, video attached (though I'm not able to see yours, I assume they're similar).
sl...@czerwinski.info.pl <sl...@czerwinski.info.pl> #3
The problem is that when the list shortens to be smaller than the viewport, the AsyncPagedListDiffer doesn't receive any signals that tell it that more needs to be loaded - it currently only loads in response to getItem(). Will fix this, but in the meantime you can workaround this by calling getItem() in onCurrentListChanged:
class MyAdapter extends PagedListAdapter<...> {
int lastPos = 0;
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
lastPos = position;
// ... regular bind code ...
}
@Override
public void onCurrentListChanged(@Nullable PagedList<Item> currentList) {
// trigger load around most recently bound item
getItem(Math.min(lastPos, getItemCount() - 1));
}
}
class MyAdapter extends PagedListAdapter<...> {
int lastPos = 0;
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
lastPos = position;
// ... regular bind code ...
}
@Override
public void onCurrentListChanged(@Nullable PagedList<Item> currentList) {
// trigger load around most recently bound item
getItem(Math.min(lastPos, getItemCount() - 1));
}
}
il...@google.com <il...@google.com> #4
In general, using a larger initial load size/prefetch distance avoids this problem as well.
We recommend page size to be several viewports worth of items (https://developer.android.com/reference/androidx/paging/PagedList.Config.Builder#setPageSize(int) ). If you follow that, you'll typically avoid this problem, as initial load size + prefetch are >= page size by default.
We recommend page size to be several viewports worth of items (
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #5
Fix merged, will likely go out after 2.0: https://android-review.googlesource.com/c/platform/frameworks/support/+/760841
Again though, I'd like to reiterate that the ideal fix is, on the app side, using a large enough initial load size that this doesn't happen.
Again though, I'd like to reiterate that the ideal fix is, on the app side, using a large enough initial load size that this doesn't happen.
il...@google.com <il...@google.com> #6
Project: platform/frameworks/support
Branch: androidx-master-dev
commit f78707abc65b00041201a995f202ee3e95c9529b
Author: Chris Craik <ccraik@google.com>
Date: Tue Sep 18 15:06:03 2018
Trigger load after pagedlist swap
Fixes: 113122599
Test: ./gradlew paging:paging-runtime:cC
If a PagedList swap results in no content changes, but a
shorter-than-viewport initial list, the PagedList would be stuck,
since no calls from the adapter would trigger loads in this case.
To work around this in many cases, trigger a load on the new PagedList
based on the last access position. This can fail if the prefetch
distance < viewport size, but that's a fairly general problem with
small prefetch windows + no placeholders.
E.g. if the end of the initial load happens to perfectly line up with
the bottom of the viewport, and no in-viewport content changes are
made, no loads below will occur. Recommendation for now in such cases
(if they happen in practice) is to make prefetch larger. We already
default to prefetch = page size, which we recommend to be several
viewports in size.
Change-Id: I0d1e2db479d1ad05fbdb34a3854279fccad9b680
M paging/runtime/src/androidTest/java/androidx/paging/AsyncPagedListDifferTest.kt
M paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
https://android-review.googlesource.com/760841
https://goto.google.com/android-sha1/f78707abc65b00041201a995f202ee3e95c9529b
Branch: androidx-master-dev
commit f78707abc65b00041201a995f202ee3e95c9529b
Author: Chris Craik <ccraik@google.com>
Date: Tue Sep 18 15:06:03 2018
Trigger load after pagedlist swap
Fixes: 113122599
Test: ./gradlew paging:paging-runtime:cC
If a PagedList swap results in no content changes, but a
shorter-than-viewport initial list, the PagedList would be stuck,
since no calls from the adapter would trigger loads in this case.
To work around this in many cases, trigger a load on the new PagedList
based on the last access position. This can fail if the prefetch
distance < viewport size, but that's a fairly general problem with
small prefetch windows + no placeholders.
E.g. if the end of the initial load happens to perfectly line up with
the bottom of the viewport, and no in-viewport content changes are
made, no loads below will occur. Recommendation for now in such cases
(if they happen in practice) is to make prefetch larger. We already
default to prefetch = page size, which we recommend to be several
viewports in size.
Change-Id: I0d1e2db479d1ad05fbdb34a3854279fccad9b680
M paging/runtime/src/androidTest/java/androidx/paging/AsyncPagedListDifferTest.kt
M paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
ap...@google.com <ap...@google.com> #7
Released with Paging 2.1.0-alpha01
Description
Version used: 1.0.0-alpha02
Devices/Android versions reproduced on: Emulator API 28, Samsung J5 API 25
Sample project attached.
I'm trying to create a custom Navigator and custom NavDestination that would animate ConstraintLayout (but any custom NavDestination would cause this issue).
Intended behaviour is shown in attached video: Layout_animations.webm
However, when I rotate the screen, while the navigation is on the custom destination, the application crashes.
The crash is caused by an unknown destination, which can only be added after custom navigator.
If I add custom destination in nav_main.xml, the app will also crash, because the navigator is not yet added.
This issue could be fixed by extending NavHostFragment, but I would need to override the whole onCreate() method.
I would need to add my custom navigator right after the line:
mNavController = new NavController(context);
I can think of 2 possible solutions in the library:
1. Delegate creating of NavController, so that a custom NavController can be provided in the XML layout file.
2. Call a new protected method "NavHostFragment.onNavControllerCreated(NavController)" right after the NavController is created, that could be overridden in a custom NavHostFragment, before the graph is created.
If there is any solution to my problem that I didn't think of, please provide a more exhaustive example in the documentation:
Stack trace:
2018-06-25 10:54:28.356 14543-14543/it.czerwinski.customnavigatorexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: it.czerwinski.customnavigatorexample, PID: 14543
java.lang.RuntimeException: Unable to start activity ComponentInfo{it.czerwinski.customnavigatorexample/it.czerwinski.customnavigatorexample.MainActivity}: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2925)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3060)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:4792)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4711)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:110)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1800)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6649)
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:826)
Caused by: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class fragment
Caused by: java.lang.IllegalStateException: unknown destination during restore: it.czerwinski.customnavigatorexample:id/animatedLayoutDestination
at androidx.navigation.NavController.onGraphCreated(NavController.java:424)
at androidx.navigation.NavController.setGraph(NavController.java:386)
at androidx.navigation.NavController.restoreState(NavController.java:742)
at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:215)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2400)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1684)
at androidx.fragment.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3772)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:120)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:395)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:377)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:467)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at it.czerwinski.customnavigatorexample.MainActivity.onCreate(MainActivity.kt:15)
at android.app.Activity.performCreate(Activity.java:7130)
at android.app.Activity.performCreate(Activity.java:7121)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1262)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2905)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3060)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:4792)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4711)
2018-06-25 10:54:28.356 14543-14543/it.czerwinski.customnavigatorexample E/AndroidRuntime: at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:110)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1800)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6649)
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:826)