在使用ViewPager2时,线上报了一个偶现错误,问题的描述是这样的:
java.lang.IllegalArgumentException
Wrong state class, expecting View State but received class
androidx.recyclerview.widget.RecyclerView$SavedState instead.
This usually happens when two views of different type have the same id in the same hierarchy.
This view's id is id/0x1. Make sure other views do not use the same id.
在文章 Android 组件提供的状态保存(saveInstanceState)与恢复(restoreInstanceState) 中我知道,这个问题是 因为 视图树中存在两个id相同的View,并且在恢复数据时出了问题。
但是页面中我们明明都是指定了id,按道理来讲是不会出现重复的呀?
通过模拟与查看源码发现,我们虽然给ViewPager2指定了Id,像这样:
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
我们都知道ViewPager2是由RecyclerView实现的,其内部还有一个View,就是RecyclerView,她的RecyclerView的id,并不是通过指定的方式确定的,而是通过一个方法自动生成的。
mRecyclerView = new RecyclerViewImpl(context);
mRecyclerView.setId(ViewCompat.generateViewId());
如果在整个视图中,有一个View的id是和ViewCompat.generateViewId()
生成的id一样的话,在数据保存与恢复时就会出问题。
我们模拟一下这种情况:
在MainActivity的布局文件中加入两个View,一个EditText(不指定id),一个ViewPager2(指定id)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/ll_root"
tools:context=".MainActivity">
<EditText
android:tag="ett"
android:layout_width=