Fixed
Status Update
Comments
il...@google.com <il...@google.com>
ma...@gmail.com <ma...@gmail.com> #2
Hi,
This looks really bad but w/o a repro app, we really cannot do anything about it. Is it possible for you to provide a sample app that reproduces your problem ?
This looks really bad but w/o a repro app, we really cannot do anything about it. Is it possible for you to provide a sample app that reproduces your problem ?
ch...@moqi.co.uk <ch...@moqi.co.uk> #3
Attached is a simple testing app. It inserts 10000 items into the db when activity starts and then displays them using paging. The db is also updated every 1 second. On the screen, if you drag the fast scroll bar up and down quickly a few times, it will eventually crash with this IndexOutOfBoundsException error.
il...@google.com <il...@google.com> #4
Thanks for the great repro case, tracked it down, investigating a fix.
Problematic behavior:
1) AsyncPagedListDiffer receives new list, takes snapshot for diffing (ui thread)
2) At roughly the same time:
2a) Diff snapshot of old snapshot vs new snapshot (bg thread)
2b) New data arrives in new list, way earlier in the list, so the list is essentially: new page, lots of empty pages, initial load
3) AsyncPagedListDiffer updates lastLoad position with diffutil position mapping
In 3, we try to map the lastLoad position from old snapshot to new snapshot, but fail to distinguish between new list vs new snapshot. Because of all the empty pages, that's a huge discrepancy. This is why the huge scrollbar + lots of swaps triggers this well - there are lots of swaps to new PagedLists while loads are happening very far away from initial load positions.
Will need to account for pages loaded in between time of snapshot, and time of swap.
Problematic behavior:
1) AsyncPagedListDiffer receives new list, takes snapshot for diffing (ui thread)
2) At roughly the same time:
2a) Diff snapshot of old snapshot vs new snapshot (bg thread)
2b) New data arrives in new list, way earlier in the list, so the list is essentially: new page, lots of empty pages, initial load
3) AsyncPagedListDiffer updates lastLoad position with diffutil position mapping
In 3, we try to map the lastLoad position from old snapshot to new snapshot, but fail to distinguish between new list vs new snapshot. Because of all the empty pages, that's a huge discrepancy. This is why the huge scrollbar + lots of swaps triggers this well - there are lots of swaps to new PagedLists while loads are happening very far away from initial load positions.
Will need to account for pages loaded in between time of snapshot, and time of swap.
Description
android.arch.navigation:navigation-fragment-ktx
android.arch.navigation:navigation-ui-ktx
Version used:
1.0.0-alpha05
Devices/Android versions reproduced on:
-SM-A510F, Android 7.0
-Emulator x86_64 API 28
Sample project:
Description:
Having this structure:
nav_graph.xml
<navigation
android:id="@+id/nav_graph"
app:startDestination="@id/startFragment">
<fragment
android:id="@+id/startFragment"
android:name="com.example.navbug.StartFragment"
android:label="StartFragment"
tools:layout="@layout/fragment_start">
<action
android:id="@+id/action_startFragment_to_nested_nav_graph"
app:destination="@id/nested_nav_graph" />
</fragment>
<include app:graph="@navigation/nested_nav_graph" />
</navigation>
nested_nav_graph.xml
<navigation
android:id="@+id/nested_nav_graph"
app:startDestination="@id/nestedStartFragment">
<fragment
android:id="@+id/nestedStartFragment"
android:name="com.example.navbug.NestedStartFragment"
android:label="NestedStartFragment">
<action
android:id="@+id/action_nestedStartFragment_to_nestedSecondFragment"
app:destination="@id/nestedSecondFragment"
app:popUpTo="@+id/nestedStartFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/nestedSecondFragment"
android:name="com.example.navbug.NestedSecondFragment"
android:label="NestedSecondFragment" />
</navigation>
I want to achieve this navigation pattern:
StartFragment => NestedStartFragment => NestedSecondFragment =(back)=> StartFragment
I'm trying to implement this by setting the action NestedStartFragment=>NestedSecondFragment with the options [popUpTo=NestedStartFragment, popUpToInclusive=true], so that the resulting stack would be:
0. NestedSecondFragment
1. NestedNavGraph
2. StartFragment
3. NavGraph
When navigating from NestedStartFragment to NestedSecondFragment, the following execption occurs:
java.lang.IllegalArgumentException: Navigator androidx.navigation.fragment.FragmentNavigator@ccc9092 reported navigation to unknown destination id com.example.navbug:id/nestedSecondFragment
at androidx.navigation.NavController$2.onNavigatorNavigated(NavController.java:142)
at androidx.navigation.Navigator.dispatchOnNavigatorNavigated(Navigator.java:217)
at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:207)
at androidx.navigation.fragment.FragmentNavigator.navigate(FragmentNavigator.java:45)
at androidx.navigation.NavDestination.navigate(NavDestination.java:407)
at androidx.navigation.NavController.navigate(NavController.java:683)
at androidx.navigation.NavController.navigate(NavController.java:630)
at androidx.navigation.NavController.navigate(NavController.java:618)
at com.example.navbug.NestedStartFragment$onViewCreated$1.onClick(Fragments.kt:31)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
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)
Right before the navigation, the stack is:
0. NestedStartFragment
1. NestedNavGraph
2. StartFragment
3. NavGraph
When NestedStartFragment is popped on my request, NestedNavGraph is also popped because
"// We never want to leave NavGraphs on the top of the stack" (from NavController.onNavigatorNavigated)
with the effect that eventually the requested destination NestedSecondFragment is pruned from the graph and cannot be reached anymore.
Unless I'm doing something wrong, it seems that NavGraph automatic popping should be avoided if the final destination actually belongs to it.