Bug P2
Status Update
Comments
jg...@google.com <jg...@google.com> #2
Hi, some follow-up questions:
1. Within the space of Xiaomi MI 9, does it only fail on Android 10, or also on previous Android versions?
2. Within the space of Android 10, does it only fail on Xiaomi MI 9, or also on other phones? Have you tried reproducing on an Android 10 emulator?
3. With Xiaomi MI 9 running Android 10, does it fail consistently or intermittently (indicating a race condition).
4. Can you elaborate a bit what you're trying to achieve with the logic around itemIds. I don't get the "Returning a new itemId so we don't store the old pages when replacing files" comment. Can you just have a collection of data : List<Pair<Id : Int, Item>> and when the collection changes, you call `adapter.notifyDatasetChanged`.
Some context which might help reproduce the issue on your side:
- The Exception thrown violates the assumption that once we are in `placeFragmentInViewHolder`, a Fragment for that ViewHolder will have already been requested and populated.
- FragmentStateAdapter expects to own page Fragments' lifecycle, so you're not expected, e.g. to remove Fragments yourself. Are you doing any operations on provided page Fragments?
[1]https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/viewpager2/viewpager2/src/main/java/androidx/viewpager2/adapter/FragmentStateAdapter.java#287
1. Within the space of Xiaomi MI 9, does it only fail on Android 10, or also on previous Android versions?
2. Within the space of Android 10, does it only fail on Xiaomi MI 9, or also on other phones? Have you tried reproducing on an Android 10 emulator?
3. With Xiaomi MI 9 running Android 10, does it fail consistently or intermittently (indicating a race condition).
4. Can you elaborate a bit what you're trying to achieve with the logic around itemIds. I don't get the "Returning a new itemId so we don't store the old pages when replacing files" comment. Can you just have a collection of data : List<Pair<Id : Int, Item>> and when the collection changes, you call `adapter.notifyDatasetChanged`.
Some context which might help reproduce the issue on your side:
- The Exception thrown violates the assumption that once we are in `placeFragmentInViewHolder`, a Fragment for that ViewHolder will have already been requested and populated.
- FragmentStateAdapter expects to own page Fragments' lifecycle, so you're not expected, e.g. to remove Fragments yourself. Are you doing any operations on provided page Fragments?
[1]
wa...@gmail.com <wa...@gmail.com> #3
1. Only fails on Android 10.
2. Only fails on Xiaomi MI 9. I tried reproducing on an Android 10 emulator but I couldn't.
3. It doesn't fail consistently since I've only seen a few crashes every few days.
4. My use case that I try to load some images and replace them with the same positions as the last (basically achieving a reverse endless scrolling) but when I try to update the adapter via adapter.notifyDatasetChanged, I still see a few images from the previous loaded data (sort of like they've been cached), a workaround of which worked for me:https://stackoverflow.com/a/11710690/2997806
What I currently attempted is to implement the workaround explained here:https://issuetracker.google.com/issues/134246546#comment8 , which seems to look promising so far in the new release we deployed. I don't think I do any operations on provided page fragments but I'll double check to see and also try to reproduce the issue, then get back to keep you updated.
2. Only fails on Xiaomi MI 9. I tried reproducing on an Android 10 emulator but I couldn't.
3. It doesn't fail consistently since I've only seen a few crashes every few days.
4. My use case that I try to load some images and replace them with the same positions as the last (basically achieving a reverse endless scrolling) but when I try to update the adapter via adapter.notifyDatasetChanged, I still see a few images from the previous loaded data (sort of like they've been cached), a workaround of which worked for me:
What I currently attempted is to implement the workaround explained here:
[Deleted User] <[Deleted User]> #4
i am facing this issue in 1.0.0 version
Fatal Exception: java.lang.IllegalStateException
Design assumption violated.
androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder + 287 (FragmentStateAdapter.java:287)
androidx.viewpager2.adapter.FragmentStateAdapter$1.onLayoutChange + 190 (FragmentStateAdapter.java:190)
android.view.View.layout + 21131 (View.java:21131)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
androidx.recyclerview.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins + 9587 (RecyclerView.java:9587)
androidx.recyclerview.widget.LinearLayoutManager.layoutChunk + 1685 (LinearLayoutManager.java:1685)
androidx.recyclerview.widget.LinearLayoutManager.fill + 1587 (LinearLayoutManager.java:1587)
androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren + 665 (LinearLayoutManager.java:665)
androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2 + 4134 (RecyclerView.java:4134)
androidx.recyclerview.widget.RecyclerView.dispatchLayout + 3851 (RecyclerView.java:3851)
androidx.recyclerview.widget.RecyclerView.onLayout + 4404 (RecyclerView.java:4404)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
androidx.viewpager2.widget.ViewPager2.onLayout + 527 (ViewPager2.java:527)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
androidx.constraintlayout.widget.ConstraintLayout.onLayout + 1915 (ConstraintLayout.java:1915)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.FrameLayout.layoutChildren + 323 (FrameLayout.java:323)
android.widget.FrameLayout.onLayout + 261 (FrameLayout.java:261)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.LinearLayout.setChildFrame + 1828 (LinearLayout.java:1828)
android.widget.LinearLayout.layoutVertical + 1656 (LinearLayout.java:1656)
android.widget.LinearLayout.onLayout + 1565 (LinearLayout.java:1565)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.FrameLayout.layoutChildren + 323 (FrameLayout.java:323)
android.widget.FrameLayout.onLayout + 261 (FrameLayout.java:261)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.LinearLayout.setChildFrame + 1828 (LinearLayout.java:1828)
android.widget.LinearLayout.layoutVertical + 1656 (LinearLayout.java:1656)
android.widget.LinearLayout.onLayout + 1565 (LinearLayout.java:1565)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.FrameLayout.layoutChildren + 323 (FrameLayout.java:323)
android.widget.FrameLayout.onLayout + 261 (FrameLayout.java:261)
com.android.internal.policy.DecorView.onLayout + 883 (DecorView.java:883)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.view.ViewRootImpl.performLayout + 3368 (ViewRootImpl.java:3368)
android.view.ViewRootImpl.performTraversals + 2809 (ViewRootImpl.java:2809)
android.view.ViewRootImpl.doTraversal + 1815 (ViewRootImpl.java:1815)
android.view.ViewRootImpl$TraversalRunnable.run + 8228 (ViewRootImpl.java:8228)
android.view.Choreographer$CallbackRecord.run + 995 (Choreographer.java:995)
android.view.Choreographer.doCallbacks + 807 (Choreographer.java:807)
android.view.Choreographer.doFrame + 739 (Choreographer.java:739)
android.view.Choreographer$FrameDisplayEventReceiver.run + 981 (Choreographer.java:981)
android.os.Handler.handleCallback + 873 (Handler.java:873)
android.os.Handler.dispatchMessage + 99 (Handler.java:99)
android.os.Looper.loop + 226 (Looper.java:226)
android.app.ActivityThread.main + 7212 (ActivityThread.java:7212)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 576 (RuntimeInit.java:576)
com.android.internal.os.ZygoteInit.main + 956 (ZygoteInit.java:956)
Fatal Exception: java.lang.IllegalStateException
Design assumption violated.
androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder + 287 (FragmentStateAdapter.java:287)
androidx.viewpager2.adapter.FragmentStateAdapter$1.onLayoutChange + 190 (FragmentStateAdapter.java:190)
android.view.View.layout + 21131 (View.java:21131)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
androidx.recyclerview.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins + 9587 (RecyclerView.java:9587)
androidx.recyclerview.widget.LinearLayoutManager.layoutChunk + 1685 (LinearLayoutManager.java:1685)
androidx.recyclerview.widget.LinearLayoutManager.fill + 1587 (LinearLayoutManager.java:1587)
androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren + 665 (LinearLayoutManager.java:665)
androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2 + 4134 (RecyclerView.java:4134)
androidx.recyclerview.widget.RecyclerView.dispatchLayout + 3851 (RecyclerView.java:3851)
androidx.recyclerview.widget.RecyclerView.onLayout + 4404 (RecyclerView.java:4404)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
androidx.viewpager2.widget.ViewPager2.onLayout + 527 (ViewPager2.java:527)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
androidx.constraintlayout.widget.ConstraintLayout.onLayout + 1915 (ConstraintLayout.java:1915)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.FrameLayout.layoutChildren + 323 (FrameLayout.java:323)
android.widget.FrameLayout.onLayout + 261 (FrameLayout.java:261)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.LinearLayout.setChildFrame + 1828 (LinearLayout.java:1828)
android.widget.LinearLayout.layoutVertical + 1656 (LinearLayout.java:1656)
android.widget.LinearLayout.onLayout + 1565 (LinearLayout.java:1565)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.FrameLayout.layoutChildren + 323 (FrameLayout.java:323)
android.widget.FrameLayout.onLayout + 261 (FrameLayout.java:261)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.LinearLayout.setChildFrame + 1828 (LinearLayout.java:1828)
android.widget.LinearLayout.layoutVertical + 1656 (LinearLayout.java:1656)
android.widget.LinearLayout.onLayout + 1565 (LinearLayout.java:1565)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.widget.FrameLayout.layoutChildren + 323 (FrameLayout.java:323)
android.widget.FrameLayout.onLayout + 261 (FrameLayout.java:261)
com.android.internal.policy.DecorView.onLayout + 883 (DecorView.java:883)
android.view.View.layout + 21112 (View.java:21112)
android.view.ViewGroup.layout + 6400 (ViewGroup.java:6400)
android.view.ViewRootImpl.performLayout + 3368 (ViewRootImpl.java:3368)
android.view.ViewRootImpl.performTraversals + 2809 (ViewRootImpl.java:2809)
android.view.ViewRootImpl.doTraversal + 1815 (ViewRootImpl.java:1815)
android.view.ViewRootImpl$TraversalRunnable.run + 8228 (ViewRootImpl.java:8228)
android.view.Choreographer$CallbackRecord.run + 995 (Choreographer.java:995)
android.view.Choreographer.doCallbacks + 807 (Choreographer.java:807)
android.view.Choreographer.doFrame + 739 (Choreographer.java:739)
android.view.Choreographer$FrameDisplayEventReceiver.run + 981 (Choreographer.java:981)
android.os.Handler.handleCallback + 873 (Handler.java:873)
android.os.Handler.dispatchMessage + 99 (Handler.java:99)
android.os.Looper.loop + 226 (Looper.java:226)
android.app.ActivityThread.main + 7212 (ActivityThread.java:7212)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 576 (RuntimeInit.java:576)
com.android.internal.os.ZygoteInit.main + 956 (ZygoteInit.java:956)
jg...@google.com <jg...@google.com> #5
We'd need reliable reproduction steps to realistically get to the bottom of this.
That includes:
- minimal working sample app
- device and OS information ; ideally something we could run on an emulator or Pixel, but if not possible (only fails on a specific popular phone model) that's OK too
Otherwise it'd be close to impossible for us to diagnose it as we're testing it quite thoroughly with the code/devices we have and not finding issues.
sm...@gmail.com <sm...@gmail.com> #6
I also had this issue on the 1.0.0 version, but the problem was that I override getItemId()
without containsItem()
After I implemented containsItem()
, problem gone. Maybe this can help somebody.
ph...@gmail.com <ph...@gmail.com> #7
Indeed it helped! Thanks!
Description
androidx.recyclerview:recyclerview:1.1.0
androidx.viewpager2:viewpager2:1.0.0
And here's the stacktrace:
```
Fatal Exception: java.lang.IllegalStateException: Design assumption violated.
at androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder(FragmentStateAdapter.java:287)
at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:276)
at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:67)
at androidx.recyclerview.widget.RecyclerView.dispatchChildAttached(RecyclerView.java:7556)
at androidx.recyclerview.widget.RecyclerView$5.addView(RecyclerView.java:860)
at androidx.recyclerview.widget.ChildHelper.addView(ChildHelper.java:107)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:8601)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8559)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1643)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:675)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:803)
at android.view.View.layout(View.java:21963)
at android.view.ViewGroup.layout(ViewGroup.java:6317)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3144)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2654)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1782)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7785)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1031)
at android.view.Choreographer.doCallbacks(Choreographer.java:854)
at android.view.Choreographer.doFrame(Choreographer.java:789)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1016)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7520)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
```
I'm not sure where this is triggered from my code since the stacktrace is not very clear, so I can't create a sample project with the bug for you to have a look at. But if it's helpful, here's my implementation of the adapter:
```
class MyAdapter(private val data: List<Data>, private val fragmentActivity: FragmentActivity)
: FragmentStateAdapter(fragmentActivity) {
private val itemIds = mutableSetOf<Long>()
private var registeredFragments = SparseArray<Fragment>()
override fun getItemCount(): Int = data.size
override fun createFragment(position: Int): Fragment {
val fragment = FileRenderHelper.findAppropriateFragment(data[position], position)
registeredFragments.put(position, fragment)
return fragment;
}
override fun getItemId(position: Int): Long {
// Returning a new itemId so we don't store the old pages when replacing files.
// Source:
return when (val data = data[position]) {
is CustomClass ->
else -> data.hashCode().toLong()
}.also { itemIds.add(it) }
}
override fun containsItem(itemId: Long): Boolean = itemIds.contains(itemId)
fun getFragmentAt(position: Int): Fragment? {
return registeredFragments[position]
}
}
```
Also, as per a similar issue, this has been solved in viewpager2:1.0.0-beta03:
[1]: