今天在调试代码的时候出现了ClassCastException直接崩溃,导致崩溃的操作是跳转到一个好友列表页面,页面和微信的通讯录页面很像,就是一个列表,右边一个导航栏,原来一直用的模拟器调试,模拟器的sdk版本是4.4的,今天换到了7.0的真机就直接崩了。
打印的错误日志如下:
java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
at android.widget.ListView.removeUnusedFixedViews(ListView.java:1908)
at android.widget.ListView.layoutChildren(ListView.java:1769)
at android.widget.AbsListView.onLayout(AbsListView.java:2161)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at com.newbeehood.widget.swipebackhelper.SwipeBackLayout.onLayout(SwipeBackLayout.java:278)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:724)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2342)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:619)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
根据日志提示,出错代码是
mContentView.layout(mContentLeft, 0,
mContentLeft + mContentView.getMeasuredWidth(),
mContentView.getMeasuredHeight());
这行代码在SwipeBackLayout类的onLayout方法中,根据提示是类型转换异常,而且是ViewGroup.LayoutParams转AbsListView.LayoutParams时出现的,页面中好友列表是用ExpandableListView实现的(其实用RecyclerView更好,只是好多年之前写过一个类似的例子是用ExpandableListView实现的,这次就直接拿来用了,不知道RecyclerView会不会出现这个问题),第一反应就是这个ExpandableListView的问题,果然在把它删掉以后就不再报错了。虽然知道是它出的问题,但是在哪里出现的类型转换却还是没有找到。仔细看了下代码,发现在ExpandableListView添加footer的时候是这样写的:
mFooterTv = new TextView(this);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DensityUtil.dp2px(this, 50));
mFooterTv.setLayoutParams(params);
mFooterTv.setGravity(Gravity.CENTER);
number = mContacts.size();
mFooterTv.setText(number + "位联系人");
contactElv.addFooterView(mFooterTv);
FooterView的LayoutParams是ViewGroup.LayoutParams,是不是这里出现的类型转换?把这行代码改成下面这样:
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, DensityUtil.dp2px(this, 50));
再次运行,果然没有问题了。
在网上查了一下,如果你要将一个view添加到另一个布局中,你必须设定该View的布局参数为其父类所使用的布局参数类型,也就是说header或者footer也要使用ListView的
LayoutParams,只是不知道为什么在4.4中运行是可以的,可能是低版本的约束比较松吧。