前几天用TableLayout和TableRow控件开发布表格布局,开发过程中一切顺利,只是在后台的日志监控中捕捉到了一个异常。通过对异常进行统计分析发现,只有华为手机才会出现,借用同事的华为手机来测试,程序在绘制表格的时候果然会出现异常。

异常的信息如下:

android.widget.LinearLayout.hasDividerBeforeChildAt(LinearLayout.java:675)
2 android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1203)
3 android.widget.TableRow.onMeasure(TableRow.java:114)
4 android.view.View.measure(View.java:17997)
5 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
6 android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1723)
7 android.widget.TableLayout.measureChildBeforeLayout(TableLayout.java:464)
8 android.widget.LinearLayout.measureVertical(LinearLayout.java:785)
9 android.widget.TableLayout.measureVertical(TableLayout.java:476)
10 android.widget.TableLayout.onMeasure(TableLayout.java:439)
11 android.view.View.measure(View.java:17997)
12 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
13 android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1723)
14 android.widget.LinearLayout.measureVertical(LinearLayout.java:785)
15 android.widget.LinearLayout.onMeasure(LinearLayout.java:654)
16 android.view.View.measure(View.java:17997)
17 android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1286)
18 android.widget.FrameLayout.onMeasure(FrameLayout.java:465)
19 android.widget.ScrollView.onMeasure(ScrollView.java:342)
20 android.view.View.measure(View.java:17997)
21 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
22 android.widget.FrameLayout.onMeasure(FrameLayout.java:465)
23 androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
24 android.view.View.measure(View.java:17997)
25 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
26 androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:401)
27 android.view.View.measure(View.java:17997)
28 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
29 android.widget.FrameLayout.onMeasure(FrameLayout.java:465)
30 android.view.View.measure(View.java:17997)
31 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
32 android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1723)
33 android.widget.LinearLayout.measureVertical(LinearLayout.java:785)
34 android.widget.LinearLayout.onMeasure(LinearLayout.java:654)
35 android.view.View.measure(View.java:17997)
36 android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5698)
37 android.widget.FrameLayout.onMeasure(FrameLayout.java:465)
38 com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2745)
39 android.view.View.measure(View.java:17997)
40 android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2412)
41 android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1414)
42 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1638)
43 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1292)
44 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6598)
45 android.view.Choreographer$CallbackRecord.run(Choreographer.java:800)
46 android.view.Choreographer.doCallbacks(Choreographer.java:603)
47 android.view.Choreographer.doFrame(Choreographer.java:572)
48 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:786)
49 android.os.Handler.handleCallback(Handler.java:815)
50 android.os.Handler.dispatchMessage(Handler.java:104)
51 android.os.Looper.loop(Looper.java:194)
52 android.app.ActivityThread.main(ActivityThread.java:5682)
53 java.lang.reflect.Method.invoke(Native Method)
54 java.lang.reflect.Method.invoke(Method.java:372)
55 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:963)
56 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:758)

然后最顶上信息如下:

java.lang.NullPointerException

Attempt to invoke virtual method 'int android.view.View.getVisibility()' on a null object reference

显然这是执行 hasDividerBeforeChildAt 函数的时候,碰到了一个空指针异常。

查了下google,在stackoverflow 上找到了提示,英文摘要如下:

The children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively MATCH_PARENT and WRAP_CONTENT.

翻译就是:TableRow 的 子View不需要明确标注layout_width 和 layout_height的值,可以使用 0dp 代替WRAP_CONTENT。TableRow 将会强制给这些属性赋值。

其实说白了,就是把TableLayout 中的 TableRow 和 TableRow中的子view 的layout_height 设定为 0dp ,问题得到解决。