Why is NPE thrown when finishing Activity?
I have an error that has been driving me crazy for days. Unfortunately, I can not show you the code for two reason, my boss will not appreciate it and the codebase is too large to share. The error occurs whenever the Activity is finishing. Weather it be because I call finish() or because the os destroys it.
The question is, what is (or could) cause execPendingActions() in FragmentManagerImpl to throw a NPE at line 1196.
Here is the stacktrace:
FragmentManagerImpl.execPendingActions() line: 1196
FragmentManagerImpl$1.run() line: 375
Handler.handleCallback(Message) line: 587
Handler.dispatchMessage(Message) line: 92
Looper.loop() line: 126
ActivityThread.main(String[]) line: 3997
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 491
ZygoteInit$MethodAndArgsCaller.run() line: 841
ZygoteInit.main(String[]) line: 59开发者_如何学C9
NativeStart.main(String[]) line: not available [native method]
When talking about finishing the activities: Are you trying to finish()
the activity from a View? Are correctly sending MyClass.this.finish()
?
It looks to me that OS force it to close due NPE. Something is wrong with the fragments. Something is Null among them. Could you at least paste the line where it crashes?
You may be hitting a bug in fragment manager where it doesn't clear its list of pending transactions before being destroyed. This can happen if you commit a transaction after your state has been saved, using FragmentTransaction.commitAllowingStateLoss(). You may be able to work around it with this code in your activity:
@Override void onDestroy() {
getFragmentManager().executePendingTransactions();
super.onDestroy();
}
You could try using the compat library and debugging that.
Alternatively try and reproduce in a cut down sample app.
The NullPointerException is caused by the fact that Activity's Handler is unset from the FragmentManager, so a "solution" that will prevent the crash is the following:
public void onDestroy(){
super.onDestroy();
try {
Field mActivityField = getFragmentManager().getClass().getDeclaredField("mActivity");
mActivityField.setAccessible(true);
mActivityField.set(getFragmentManager(), this);
Field mPendingActionsField = getFragmentManager().getClass().getDeclaredField("mPendingActions");
mPendingActionsField.setAccessible(true);
mPendingActionsField.set(getFragmentManager(), null);
Field f = Activity.class.getDeclaredField("mHandler");
f.setAccessible(true);
Handler handler = (Handler) f.get(this);
handler.close();
} catch (Throwable e) {
}
}
精彩评论