如何修复 ViewPager2 中的 'Design assumption violated' 错误?
How to fix 'Design assumption violated' error in ViewPager2?
我正在使用 ViewPager2、Kotlin 和 AndroidX。
当适配器不在索引 0 并且我更改适配器列表并将当前项设置为索引 0 时,将引发异常。
java.lang.IllegalStateException: Design assumption violated.
at androidx.viewpager2.widget.ViewPager2.updateCurrentItem(ViewPager2.java:538)
at androidx.viewpager2.widget.ViewPager2.onAnimationsFinished(ViewPager2.java:518)
at androidx.recyclerview.widget.RecyclerView$ItemAnimator.isRunning(RecyclerView.java:13244)
at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:515)
at android.view.View.layout(View.java:15596)
在ViewPager2的第537行有一个if导致了异常:
// Extra checks verifying assumptions
// TODO: remove after testing
View snapView1 = mPagerSnapHelper.findSnapView(mLayoutManager);
View snapView2 = mLayoutManager.findViewByPosition(snapPosition);
if (snapView1 != snapView2) {
throw new IllegalStateException("Design assumption violated.");
}
这是我更新适配器列表的方式:
adapter.list = newList
adapter.notifyDataSetChanged()
viewpager.setCurrentItem(0, true)
只有当smoothScroll
设置为true
时才会发生
我错过了什么?
编辑:
我正在使用 androidx.viewpager2.widget.ViewPager2
com.google.android.material:material:1.1.0-alpha08
我遇到了同样的问题,但该错误似乎已在当前版本中修复(至少对我而言)androidx.viewpager2:viewpager2:1.0.0-beta01
。
中查看更多内容
我在 ViewPager2 配置更改时遇到了同样的问题。我正在使用:
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta03'
在我的例子中,我覆盖了 FragmentStateAdapter class 中的 getItemId()
方法。当我摆脱我的 getItemId()
方法时,“IllegalStateException:违反设计假设”错误不再存在! :-)
我正在使用 androidx.viewpager2:viewpager2:1.0.0
对于那些仍然坚持这一点的人,需要实施 getItemId()
containsItem()
。请检查您的 getItemId()
和 containsItem()
实施。我的问题是当我提供 10 件商品时 可能有几件商品具有相同的值 ,出现此错误。
媒体有多个具有相同值的数据。
private var mediaId = media.map { it.hashCode().toLong() }
override fun getItemId(position: Int): Long = mediaId[position]
override fun containsItem(itemId: Long): Boolean = mediaId.contains(itemId)
当您更新数据甚至只是滑动时,viewpager 会很混乱,因为您使用非唯一 ID 实现了 getItemId()
。解决方案只是 确保您的数据是唯一的或拥有自己的 ID。 *我的媒体数据没有 ID。
If you open the implementation of getItemId()
notes this part :
- @return stable item id {@link RecyclerView.Adapter#hasStableIds()}
you need to have unique id for each of item.
我的问题是我正在自定义 containsItem()
以在某些条件下从 ViewPager
中删除片段,然后 return false
;
旋转phone(然后滑动ViewPager2
)后遇到Design assumption violated
。
我通过 return 超级 class 方法解决了这个问题:return super.containsItem(itemId);
@Override
public boolean containsItem(long itemId) {
// Your code
return super.containsItem(itemId);
}
更新:
The containsItem method does not have the "CallSuper" annotation and is therefore not required to be called
没错,不用调用super;在 returning 一个布尔值之前我没有明确地调用它;只是 return 解决这个问题
这是一个简单用例的解决方案
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
class ViewPager2Adapter(
val dataList: List<Item> = listOf(),
fragmentActivity: FragmentActivity
) :
FragmentStateAdapter(fragmentActivity) {
val pageIds= dataList.map { it.hashCode().toLong() }.toMutableList()
override fun createFragment(position: Int): Fragment {
return MyFragment.newInstance(dataList[position])
}
override fun getItemCount(): Int {
return dataList.size
}
override fun getItemId(position: Int): Long {
return pageIds[position]
}
override fun containsItem(itemId: Long): Boolean {
return pageIds.contains(itemId)
}
}
然后我遇到了一个特定的用例,当我用一个新的对象替换该位置的对象时,我得到了异常。
解法:
现在,如果您正在对适配器进行数据更改,即用新对象替换 dataList 中的对象,请确保将旧对象的 pageIds 中的 id 替换为新对象。
(viewPager2.adapter as? ViewPager2Adapter)?.apply {
pageIds[oldIndex] = (NewItemObject).hashCode().toLong()
notifyItemChanged(oldIndex)
}
我正在使用 ViewPager2、Kotlin 和 AndroidX。 当适配器不在索引 0 并且我更改适配器列表并将当前项设置为索引 0 时,将引发异常。
java.lang.IllegalStateException: Design assumption violated.
at androidx.viewpager2.widget.ViewPager2.updateCurrentItem(ViewPager2.java:538)
at androidx.viewpager2.widget.ViewPager2.onAnimationsFinished(ViewPager2.java:518)
at androidx.recyclerview.widget.RecyclerView$ItemAnimator.isRunning(RecyclerView.java:13244)
at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:515)
at android.view.View.layout(View.java:15596)
在ViewPager2的第537行有一个if导致了异常:
// Extra checks verifying assumptions
// TODO: remove after testing
View snapView1 = mPagerSnapHelper.findSnapView(mLayoutManager);
View snapView2 = mLayoutManager.findViewByPosition(snapPosition);
if (snapView1 != snapView2) {
throw new IllegalStateException("Design assumption violated.");
}
这是我更新适配器列表的方式:
adapter.list = newList
adapter.notifyDataSetChanged()
viewpager.setCurrentItem(0, true)
只有当smoothScroll
设置为true
我错过了什么?
编辑:
我正在使用 androidx.viewpager2.widget.ViewPager2
com.google.android.material:material:1.1.0-alpha08
我遇到了同样的问题,但该错误似乎已在当前版本中修复(至少对我而言)androidx.viewpager2:viewpager2:1.0.0-beta01
。
我在 ViewPager2 配置更改时遇到了同样的问题。我正在使用:
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta03'
在我的例子中,我覆盖了 FragmentStateAdapter class 中的 getItemId()
方法。当我摆脱我的 getItemId()
方法时,“IllegalStateException:违反设计假设”错误不再存在! :-)
我正在使用 androidx.viewpager2:viewpager2:1.0.0
对于那些仍然坚持这一点的人,需要实施 getItemId()
containsItem()
。请检查您的 getItemId()
和 containsItem()
实施。我的问题是当我提供 10 件商品时 可能有几件商品具有相同的值 ,出现此错误。
媒体有多个具有相同值的数据。
private var mediaId = media.map { it.hashCode().toLong() }
override fun getItemId(position: Int): Long = mediaId[position]
override fun containsItem(itemId: Long): Boolean = mediaId.contains(itemId)
当您更新数据甚至只是滑动时,viewpager 会很混乱,因为您使用非唯一 ID 实现了 getItemId()
。解决方案只是 确保您的数据是唯一的或拥有自己的 ID。 *我的媒体数据没有 ID。
If you open the implementation of
getItemId()
notes this part :
- @return stable item id {@link RecyclerView.Adapter#hasStableIds()}
you need to have unique id for each of item.
我的问题是我正在自定义 containsItem()
以在某些条件下从 ViewPager
中删除片段,然后 return false
;
旋转phone(然后滑动ViewPager2
)后遇到Design assumption violated
。
我通过 return 超级 class 方法解决了这个问题:return super.containsItem(itemId);
@Override
public boolean containsItem(long itemId) {
// Your code
return super.containsItem(itemId);
}
更新:
The containsItem method does not have the "CallSuper" annotation and is therefore not required to be called
没错,不用调用super;在 returning 一个布尔值之前我没有明确地调用它;只是 return 解决这个问题
这是一个简单用例的解决方案
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
class ViewPager2Adapter(
val dataList: List<Item> = listOf(),
fragmentActivity: FragmentActivity
) :
FragmentStateAdapter(fragmentActivity) {
val pageIds= dataList.map { it.hashCode().toLong() }.toMutableList()
override fun createFragment(position: Int): Fragment {
return MyFragment.newInstance(dataList[position])
}
override fun getItemCount(): Int {
return dataList.size
}
override fun getItemId(position: Int): Long {
return pageIds[position]
}
override fun containsItem(itemId: Long): Boolean {
return pageIds.contains(itemId)
}
}
然后我遇到了一个特定的用例,当我用一个新的对象替换该位置的对象时,我得到了异常。
解法: 现在,如果您正在对适配器进行数据更改,即用新对象替换 dataList 中的对象,请确保将旧对象的 pageIds 中的 id 替换为新对象。
(viewPager2.adapter as? ViewPager2Adapter)?.apply {
pageIds[oldIndex] = (NewItemObject).hashCode().toLong()
notifyItemChanged(oldIndex)
}