0

我提前为这篇文章的长度道歉,但是包含两个 LogCat 输出对于清楚地解释我的问题是必要的。

当我为我的自定义 ViewGroup 调用侦听器的接口方法之一时,我收到了 NullPointerException。异常发生在下面代码的第 264 行。

260    ValueTab valueTab = mTabHost.getCurrentlySelectedValueTab();
261    if (this != null && valueTab != null) {
262        Log.i("TabbedSlider", this.toString());
263        Log.i("ValueTab", valueTab.toString());
264        mOnTabbedSliderChangeListener.onSliderValueChanged(this, valueTab);
265    }

我已将方法调用放在 if 语句中,以确保两个参数都不为空。我还包含了一些 Log 语句,以帮助澄清调用时参数的状态。

  • this...是我的自定义 ViewGroup 的一个实例,名为TabbedSlider
  • valueTab... 是 TabbedSlider 的自定义子视图的一个实例,该视图的类型称为ValueTab显示标题和浮点值。

下面的顺序解释了这个方法调用发生的时间:

  • TabbedSlider 的一个实例被实例化。
  • 设置了它的各种属性。
  • 它被添加到 MainActivity。
  • ValueTab 的一个实例被实例化。
  • 设置了它的各种属性,包括为其分配值。
  • 它被添加到 TabbedSlider 的实例中。
  • 进行了有问题的方法调用。

我在问题方法调用上设置了一个断点并运行调试。然后,当我检查thisandvalueTab时,它们按我预期的方式设置。

由于此方法调用是在将 ValueTab 添加到 TabbedSlider 后立即进行的,因此它们尚未被测量、布局和绘制到屏幕上(因此当我记录它们时它们的边界值为 0 toString()),但这些对象绝对不是 null .

这是 LogCat 输出:

10-07 10:28:17.952: D/dalvikvm(13357): GC_FOR_ALLOC freed 341K, 6% free 7644K/8048K, paused 36ms, total 37ms
10-07 10:28:17.972: I/TabbedSlider(13357): com.soundconception.tabbedslider.TabbedSlider{42075068 V.E..... ......I. 0,0-0,0 #7f040002 app:id/testSliderA}
10-07 10:28:17.972: I/ValueTab(13357): com.soundconception.tabbedslider.ValueTab{420d8908 VFED..C. ..S...I. 0,0-0,0}
10-07 10:28:17.972: D/AndroidRuntime(13357): Shutting down VM
10-07 10:28:17.972: W/dalvikvm(13357): threadid=1: thread exiting with uncaught exception (group=0x41911700)
10-07 10:28:17.972: E/AndroidRuntime(13357): FATAL EXCEPTION: main
10-07 10:28:17.972: E/AndroidRuntime(13357): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.soundconception.tabbedslider/com.soundconception.tabbedslider.MainActivity}: java.lang.NullPointerException
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.ActivityThread.access$600(ActivityThread.java:141)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.os.Handler.dispatchMessage(Handler.java:99)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.os.Looper.loop(Looper.java:137)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.ActivityThread.main(ActivityThread.java:5103)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at java.lang.reflect.Method.invokeNative(Native Method)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at java.lang.reflect.Method.invoke(Method.java:525)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at dalvik.system.NativeStart.main(Native Method)
10-07 10:28:17.972: E/AndroidRuntime(13357): Caused by: java.lang.NullPointerException
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabbedSlider.configureSliderForValueTab(TabbedSlider.java:264)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabbedSlider.access$1(TabbedSlider.java:256)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabbedSlider$2.onValueTabSelectionChange(TabbedSlider.java:164)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabHost.selectValueTab(TabHost.java:88)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabHost.valueTabSetup(TabHost.java:72)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabHost.addValueTab(TabHost.java:51)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.TabbedSlider.addValueTab(TabbedSlider.java:249)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at com.soundconception.tabbedslider.MainActivity.onCreate(MainActivity.java:18)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.Activity.performCreate(Activity.java:5133)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
10-07 10:28:17.972: E/AndroidRuntime(13357):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
10-07 10:28:17.972: E/AndroidRuntime(13357):    ... 11 more

我可以通过将方法调用放在 try/catch 块中来解决这个问题,如下所示:

    ValueTab valueTab = mTabHost.getCurrentlySelectedValueTab();
    if (this != null && valueTab != null) {
        Log.i("TabbedSlider", this.toString());
        Log.i("ValueTab", valueTab.toString());
        try {
            mOnTabbedSliderChangeListener.onSliderValueChanged(this, valueTab);
        } catch (NullPointerException e) {
            Log.i("TabbedSlider", "Caught NullPointerException");
        }           
    }

当我运行它时,第一次为我的 3 个 TabbedSlider 实例中的每一个调用该方法时会捕获 NullPointerException,但第一次调用之后的任何后续调用都可以正常工作而不会引发异常,如以下新的 LogCat 输出所示。

10-07 11:36:53.822: D/dalvikvm(14479): GC_FOR_ALLOC freed 347K, 6% free 7643K/8052K, paused 36ms, total 38ms
10-07 11:36:53.852: I/TabbedSlider(14479): com.soundconception.tabbedslider.TabbedSlider{42076c68 V.E..... ......I. 0,0-0,0 #7f040002 app:id/testSliderA}
10-07 11:36:53.852: I/ValueTab(14479): com.soundconception.tabbedslider.ValueTab{420da508 VFED..C. ..S...I. 0,0-0,0}
10-07 11:36:53.852: I/TabbedSlider(14479): Caught NullPointerException
10-07 11:36:53.862: I/TabbedSlider(14479): com.soundconception.tabbedslider.TabbedSlider{420b7768 V.E..... ......I. 0,0-0,0 #7f040003 app:id/testSliderB}
10-07 11:36:53.862: I/ValueTab(14479): com.soundconception.tabbedslider.ValueTab{4206e0c0 VFED..C. ..S...I. 0,0-0,0}
10-07 11:36:53.862: I/TabbedSlider(14479): Caught NullPointerException
10-07 11:36:53.882: I/TabbedSlider(14479): com.soundconception.tabbedslider.TabbedSlider{420c8378 V.E..... ......I. 0,0-0,0 #7f040004 app:id/testSliderC}
10-07 11:36:53.882: I/ValueTab(14479): com.soundconception.tabbedslider.ValueTab{42077768 VFED..C. ..S...I. 0,0-0,0}
10-07 11:36:53.882: I/TabbedSlider(14479): Caught NullPointerException
10-07 11:36:53.902: D/HardwareRenderer(14479): Profiling hardware renderer
10-07 11:36:53.952: D/libEGL(14479): loaded /system/lib/egl/libEGL_tegra.so
10-07 11:36:53.972: D/libEGL(14479): loaded /system/lib/egl/libGLESv1_CM_tegra.so
10-07 11:36:53.982: D/libEGL(14479): loaded /system/lib/egl/libGLESv2_tegra.so
10-07 11:36:54.022: D/OpenGLRenderer(14479): Enabling debug mode 0
10-07 11:37:15.252: I/TabbedSlider(14479): com.soundconception.tabbedslider.TabbedSlider{420b7768 V.E..... ......ID 21,127-779,233 #7f040003 app:id/testSliderB}
10-07 11:37:15.262: I/ValueTab(14479): com.soundconception.tabbedslider.ValueTab{420581e8 VFED..C. ..SP..ID 93,0-186,54}
10-07 11:37:29.292: I/TabbedSlider(14479): com.soundconception.tabbedslider.TabbedSlider{420c8378 V.E..... ......ID 21,233-779,339 #7f040004 app:id/testSliderC}
10-07 11:37:29.292: I/ValueTab(14479): com.soundconception.tabbedslider.ValueTab{42074f48 VFED..C. ..SP..ID 186,0-279,54}
10-07 11:37:32.572: I/TabbedSlider(14479): com.soundconception.tabbedslider.TabbedSlider{42076c68 V.E..... ......ID 21,21-779,127 #7f040002 app:id/testSliderA}
10-07 11:37:32.572: I/ValueTab(14479): com.soundconception.tabbedslider.ValueTab{4209bcc8 VFED..C. ..SP..ID 188,0-282,54}

看来这归结为与第一次通话时尚未绘制的视图有关,但我不明白为什么。此时的视图对象不为空,为什么会引发 NullPointerException 呢?显然,我的理解存在漏洞。

虽然我可以解决 try/catch 块的问题,但不理解为什么会首先发生异常会让我发疯。任何解释将不胜感激,也有助于这个代码猴子保持理智。

4

0 回答 0