项目开发中碰到一个异常比较奇怪,因为这个异常一旦出现会然你很头疼,因为从奔溃日志中你基本找不到有用的信息,比如这个:
java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.LinearLayout$LayoutParams
at android.widget.LinearLayout.measureVertical(LinearLayout.java:720)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:629)
at android.view.View.measure(View.java:20171)
at android.widget.ListView.setupChild(ListView.java:2031)
at android.widget.ListView.makeAndAddView(ListView.java:1950)
at android.widget.ListView.fillSpecific(ListView.java:1379)
at android.widget.ListView.layoutChildren(ListView.java:1746)
at android.widget.AbsListView.onLayout(AbsListView.java:2723)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:630)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1731)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1496)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1080)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1742)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:344)
at android.widget.FrameLayout.onLayout(FrameLayout.java:281)
at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:3178)
at android.view.View.layout(View.java:17945)
at android.view.ViewGroup.layout(ViewGroup.java:5812)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2716)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2417)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1487)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7450)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
at android.view.Choreographer.doCallbacks(Choreographer.java:695)
at android.view.Choreographer.doFrame(Choreographer.java:631)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7225)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
从log中看这个异常,信息中没有报类似的cause by信息,也就找不到异常出现在项目中的哪行代码。这个时候你可能会去点源码中的listView的代码,因为log中出现ndroid.widget.ListView类似信息,一番折腾下来然而并没有什么软用,怎么办呢?
这个时候我就去分析对比异常出现前后的代码,异常出现前后改动的布局文件,当然也会分析下ListView附近的改动代码。如上的这个异常是这么出现的:
一开始分析ListView也没分析出啥原因,后面看到View一开始是RelativeLayout的子View,后面View作为了LinearLayout的子View就出现了上面的异常;到这里还没看懂异常的原因,然后分析代码,结果看到这么一段我有一个View一开始是放在RelativeLayout里,此时运行Ok,然后我把这个View放到了一个LinearLayout里并且单独提出来作为一个layout,之后我又调用了ListView的addHeader方法把这个layout Add进去了,因此出现了上面的错误,
RelativeLayout.LayoutParams gallery_lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height); slider.setLayoutParams(gallery_lp);View指的就是slider,顿时焕然大悟。然后我就把如上代码改成如下,异常就没了。
LinearLayout.LayoutParams gallery_lp = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height); slider.setLayoutParams(gallery_lp);原因就是因为slider之后作为了LinearLayout的子View,它的Layoutparams就因该是它的父View的LayoutParams,所以就应该把slider的LayoutParams从RelativeLayout$LayoutParams改成LinearLayout$LayoutParams。
写这个的原因就是告诉自己,遇到这样的错误,就因该从这几个步骤解决问题:
- 基本的定位异常出现的代码行数,分析...
- 代码回退,然后对比分析代码找原因
- 分析异常前后改动的Layout文件
- 分析改动的View在代码中的调用