I持っNPEによって引き起こされるクラッシュのための次のスタックトレース:Androidのアクティビティとフラグメントライフサイクルの問題?
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.daybreak.my.app/com.daybreak.my.app.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ViewSwitcher.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2430)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
at android.app.ActivityThread.access$900(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1358)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5456)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:735)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ViewSwitcher.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.daybreak.my.app.TimesFragment.onLocationChange(TimesFragment.java:446)
at com.daybreak.my.app.MainActivity.onLocationChange(MainActivity.java:289)
at com.daybreak.my.app.MainActivity.onCreate(MainActivity.java:112)
at android.app.Activity.performCreate(Activity.java:6302)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2383)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
at android.app.ActivityThread.access$900(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1358)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5456)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:735)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
次のように私はセットアップを持っている方法は、私のアプリは、次のとおりです。
MainActivity
public class MainActivity extends AppCompatActivity implements LocationChangeListener {
@Override
public void onCreate(Bundle savedInstanceState) {
//...
onLocationChange(LocationManager.getSavedLocation(this)); // Manually calling onLocationChange() method
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) return;
showFragment(new TimesFragment(), TimesFragment.TAG);
}
}
@Override
public void onLocationChange(Locatin location) {
if (location == null) return;
//...
// Call attached onLocationChange() if it implements LocationChangeListener
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (f instanceof LocationChangeListener)
((LocationChangeListener) f).onLocationChange(location);
}
}
TimesFragmentを
public class TimesFragment extends Fragment implements LocationChangeListener {
private ViewSwitcher viewSwitcher;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//...
viewSwitcher = (ViewSwitcher) view.findViewById(R.id.view_switcher);
}
@Override
public void onLocationChange(Location location) {
this.location = location;
viewSwitcher.setOnClickListener(null); //<-- NPE Cause here
updateContent();
}
}
私の了解 Activity.onCreate()
は、新しく起動した後、またはユーザーが明示的にユーザーによって、または他のアプリケーションメモリが必要)。これが起こった場合、フラグメントも破棄され、作成する必要があります。つまり、フラグメントのonCreateView()
が呼び出されます。そのため、onLocationChange()
をMainActivity.onCreate()
から呼び出す前に、内のfindFragmentById()
はフラグメントを検出しないため安全です。
リアリティ スタックトレースから、MainActivity.onCreate()
からコールが開始されたことがわかります。しかし私にとって困惑しているのは、onLocationChange()
がMainActivity.onCreate()
の中から呼び出されたときに、onLocationChange()
内のfindFragmentById()
がそのフラグメントを見つけて、onLocationChange()
というフラグメントを呼び出すということです。この場合、viewSwitcher
はNULL
であり、アプリがクラッシュする原因となります。
明らかに、フラグメントは既にビューコンテナに追加されており、フラグメントonCreateView()
はまだ呼び出されていません。
QUESTION
私はこのクラッシュを再作成することができ、これを引き起こしているライフサイクルプロセスのわからないではないと思います。
だから、誰もがこのエラーを再現し、NPEを引き起こしている流れに責任がある
- を伝えることができますか?
FindViewByIdは、特定の条件ではnullを返します。なぜそれがライフサイクルの問題なのか分かりません –
フラグメントのXMLレイアウトから 'view_switcher'を除外することでエラーを非常に簡単に再現することができます –
@ cricket_007ユーザーがフラグメントのXMLファイルを編集しているのではないか...ユーザデバイス上で動作しているときに発生します。 – fahmy