11

我正在使用 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$4.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

4

5 回答 5

13

ViewPager2在配置更改时遇到了同样的问题。我在用着:

implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta03'

就我而言,我已经覆盖了FragmentStateAdaptergetItemId()中的方法。当我摆脱我的方法时,“ IllegalStateException:违反设计假设”错误就消失了!:-)getItemId()

于 2019-08-28T11:35:20.757 回答
10

我在用着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 会感到困惑,因为您getItemId()使用非唯一 ID 实现。解决方案只是确保您的数据是唯一的或有自己的 id。*我的媒体数据没有 ID。

如果你打开这部分的执行getItemId()注释:

  • @return 稳定项目 ID {@link RecyclerView.Adapter#hasStableIds()}

您需要为每个项目提供唯一的 ID。

于 2020-07-27T11:19:21.317 回答
0

我遇到了同样的问题,但在当前版本中该错误似乎已修复(至少对我而言)androidx.viewpager2:viewpager2:1.0.0-beta01

在ViewPager2 1.0.0-beta01 发行说明中查看更多信息

于 2019-07-19T10:30:34.223 回答
0

这是一个简单用例的解决方案

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)
}
于 2022-02-21T07:52:13.193 回答
-1

我的问题是我正在定制containsItem()一些条件,在这些条件下我从 中删除 Fragments ViewPager,然后返回false

我在旋转手机后遇到Design assumption violated(然后滑动ViewPager2)。

我通过返回超类方法解决了这个问题:return super.containsItem(itemId);

@Override
public boolean containsItem(long itemId) {
    // Your code
    return super.containsItem(itemId);
}

更新:

containsItem 方法没有“CallSuper”注解,因此不需要调用

这是对的,不需要调用super;在返回布尔值之前我没有明确调用它;只是返回它来解决这个问题

于 2020-09-10T00:41:19.683 回答