この投稿が長くなってしまったことを前もってお詫びしますが、問題を明確に説明するには、2 つの LogCat 出力を含める必要がありました。
カスタム ViewGroup のリスナーの Interface メソッドの 1 つを呼び出すと、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 }
どちらの引数も null にならないように、if ステートメント内にメソッド呼び出しを配置しました。呼び出しが行われたときの引数の状態を明確にするために、いくつかの Log ステートメントも含めました。
this
... と呼ばれるカスタム ViewGroup のインスタンスですTabbedSlider
valueTab
ValueTab
... は、タイトルとフロート値を表示する、呼び出されたタイプの TabbedSlider のカスタム子ビューのインスタンスです。
以下のシーケンスは、このメソッド呼び出しがいつ発生するかを説明しています。
- TabbedSlider のインスタンスがインスタンス化されます。
- そのさまざまなプロパティが設定されます。
- MainActivity に追加されます。
- ValueTab のインスタンスがインスタンス化されます。
- 値の割り当てなど、さまざまなプロパティが設定されます。
- TabbedSlider のインスタンスに追加されます。
- 問題のあるメソッド呼び出しが行われます。
問題のメソッド呼び出しにブレーク ポイントを設定し、デバッグを実行しました。次に と を調べるthis
とvalueTab
、期待どおりにセットアップされています。
このメソッド呼び出しは 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}
これは、最初の呼び出し時にまだビューが描画されていないことに関係しているように見えますが、その理由はわかりません。この瞬間のビュー オブジェクトは null ではないのに、NullPointerException が発生するのはなぜですか? 明らかに私の理解に穴があります。
try/catch ブロックを使用して問題を回避できますが、そもそもなぜ例外が発生するのかを理解していないと気が狂ってしまいます。どんな説明でも大歓迎です。また、このコード モンキーが正気を保つのにも役立ちます。