先看异常日志:
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.xxx/com.xxx.xxx.activity.Activity}: java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class android.widget.GridView$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/pull_refresh_gridview. Make sure other views do not use the same id.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2092)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2117)
at android.app.ActivityThread.access$600(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1213)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4914)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:808)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:575)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class android.widget.GridView$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/pull_refresh_gridview. Make sure other views do not use the same id.
at android.view.View.onRestoreInstanceState(View.java:12053)
at android.view.View.dispatchRestoreInstanceState(View.java:12029)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2697)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2703)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2703)
at android.view.View.restoreHierarchyState(View.java:12007)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:447)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:949)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1884)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1514)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1884)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:566)
at com.esbook.reader.activity.ActFragmentContent.onStart(ActFragmentContent.java:232)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1163)
at com.lbe.security.service.core.client.b.x.callActivityOnStart(Unknown Source)
at android.app.Activity.performStart(Activity.java:5096)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2065)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2117)
at android.app.ActivityThread.access$600(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1213)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4914)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:808)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:575)
at dalvik.system.NativeStart.main(Native Method)
怀疑:看似问题是在Fragment 中,实际问题还是在View中:two views of different type have the same id
解决方案:给View设置一个动态生成的Id:gridview.setId(R.id.gridview);
通过观察view初始化时的id发现:setId之前
07-21 11:29:24.539: D/GridView(12492): pullToRefreshBase id 2131362660
07-21 11:29:24.539: D/GridView(12492): absListView id 2131362660
两种view Id一毛一样!
setId之后:
07-21 11:30:44.805: D/GridView(13144): pullToRefreshBase id 2131362660
07-21 11:30:44.805: D/GridView(13144): absListView id 2131361795
两种view Id 不一样!
为什么?
问题关键点在于two views of different type have the same id的描述,不同类型的view拥有同一个id,结合博客园一个大神关于View的onRestoreInstanceState及onSaveInstanceState的分析结论:“当你的View确定要save/restore状态的时候,一定要保证他们有unique的id!因为Android内部用id作为保存、恢复状态时使用的Key(SparseArray的key),否则就会发生一个覆盖另一个的悲剧”!(博客园是个好地方,原文看这:http://www.cnblogs.com/xiaoweiz/p/3813914.html)。
情景再现:不知道怎么实际使用中怎么发生的,但是通过开发选项设置为不保留活动,离开页面即销毁该页面;退入后台或跳入其他页面,再返回该页面时就可以复现,因此没有给该View设置Id的时候,就会得到跟上面日志一个模子里刻出来的异常日志。
: 使用自定义下拉刷新View ,在静态代码findViewById中取出xml布局文件里的下拉刷新view 后,再去获取该控件内部包含的可刷新View对象,最终得到的View对象Id需要一个Id,为了保证在View的OnSaveInstanceState时保存状态时不被其他类型的view覆盖掉,那就要保证key值唯一,这样在onRestore时才会找到正确的那个View对象!因此在实例化这个View时,给他一个Id,动态生成也好,findViewById也好,就看这个view是怎么来的了。这里这个view是动态实例化的,非xml文件,因此使用setId这个方法,而这个Id便来源于我们的定义的ids文件(xml)。
没有搞明白的点:动态实例化的View在没有设置Id之前,为什么会使用到他父类的id?
共同学习,写下你的评论
评论加载中...
作者其他优质文章