问题
I'm using the android support library v4 revision 11 and time to time, I see the stack trace below ; I suspect it's happening due to a launch from recents, hence the model I'm trying to access is null. Anyhow, this trace has made me wonder why onCreateView is called when the activity is being destroyed, and what's the best way to handle such cases?
java.lang.NullPointerException
at com.example.dialogs.ExampleDialogFragment.onCreateView(ExampleDialogFragment.java:53)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
at android.support.v4.app.FragmentManagerImpl.dispatchReallyStop(FragmentManager.java:1888)
at android.support.v4.app.FragmentActivity.onReallyStop(FragmentActivity.java:787)
at android.support.v4.app.FragmentActivity.doReallyStop(FragmentActivity.java:764)
at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:322)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3642)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3673)
at android.app.ActivityThread.access$2900(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
After the crash an activity from back-stack is resumed, I do check if the model is valid at activities onResume()
, onStart()
and onCreate(Bundle savedInstanceState)
. If the model is not valid I start another activity from there with FLAG_ACTIVITY_NO_HISTORY
, call finish()
and return;
e.g.
@Override
public void onResume() {
Model cm = Application.getModel();
final boolean isModelAvailable = cm != null;
if (!isModelAvailable) {
Intent restartIntent = IntentUtil.intentForAction(Constants.INTENT_RESTART);
restartIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(restartIntent);
finish();
super.onResume();
return;
} else {
}
after INTENT_RESTART
activity is finished with reinitializing the model it starts activity with flags FLAG_ACTIVITY_CLEAR_TOP
, this activity commits transaction to the fragment FirstFragment
See the log with FragmentManager.enableDebugLogging(true);
.
05-13 13:24:53.051: V/FragmentManager(7468): Commit: BackStackEntry{40710fa0}
05-13 13:24:53.111: V/FragmentManager(7468): Commit: BackStackEntry{40771e78}
05-13 13:24:53.151: V/FragmentManager(7468): Run: BackStackEntry{40710fa0}
05-13 13:24:53.151: V/FragmentManager(7468): add: RetainFragment{4077d048 app_ImageCache}
05-13 13:24:53.151: V/FragmentManager(7468): Allocated fragment index RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:24:53.151: V/FragmentManager(7468): moveto CREATED: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:24:53.151: V/FragmentManager(7468): moveto ACTIVITY_CREATED: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:24:53.151: V/FragmentManager(7468): Run: BackStackEntry{40771e78}
05-13 13:24:53.151: V/FragmentManager(7468): add: FirstFragment{4077dfa8 id=0x7f04000d}
05-13 13:24:53.151: V/FragmentManager(7468): Allocated fragment index FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:24:53.151: V/FragmentManager(7468): moveto CREATED: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:24:53.151: V/FragmentManager(7468): moveto ACTIVITY_CREATED: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:24:53.791: V/FragmentManager(7468): moveto STARTED: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:24:53.791: V/FragmentManager(7468): moveto STARTED: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:24:53.811: V/FragmentManager(7468): moveto RESUMED: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:24:53.811: V/FragmentManager(7468): moveto RESUMED: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:25:58.414: V/FragmentManager(7468): Commit: BackStackEntry{40727530}
05-13 13:25:58.434: V/FragmentManager(7468): Run: BackStackEntry{4078fe00}
05-13 13:25:58.434: V/FragmentManager(7468): add: RetainFragment{4076f1b0 app_ImageCache}
05-13 13:25:58.434: V/FragmentManager(7468): Allocated fragment index RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:25:58.434: V/FragmentManager(7468): moveto CREATED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:25:58.434: V/FragmentManager(7468): moveto ACTIVITY_CREATED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:25:58.434: V/FragmentManager(7468): Run: BackStackEntry{40727530}
05-13 13:25:58.434: V/FragmentManager(7468): add: SecondFragment{40713c28 id=0x7f04000d}
05-13 13:25:58.434: V/FragmentManager(7468): Allocated fragment index SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:25:58.434: V/FragmentManager(7468): moveto CREATED: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:25:58.434: V/FragmentManager(7468): moveto ACTIVITY_CREATED: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:25:58.545: V/FragmentManager(7468): moveto STARTED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:25:58.545: V/FragmentManager(7468): moveto STARTED: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:25:58.565: V/FragmentManager(7468): moveto RESUMED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:25:58.565: V/FragmentManager(7468): moveto RESUMED: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:26:02.338: V/FragmentManager(7468): Saved state of RetainFragment{4077d048 #0 app_ImageCache}: null
05-13 13:26:02.338: V/FragmentManager(7468): Saved state of FirstFragment{4077dfa8 #1 id=0x7f04000d}: Bundle[{android:view_state=android.util.SparseArray@40b15b60}]
05-13 13:26:02.338: V/FragmentManager(7468): saveAllState: adding fragment #0: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:26:02.338: V/FragmentManager(7468): saveAllState: adding fragment #1: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:26:02.348: V/FragmentManager(7468): movefrom STARTED: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:26:02.348: V/FragmentManager(7468): movefrom STARTED: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:26:02.358: V/FragmentManager(7468): movefrom STOPPED: RetainFragment{4077d048 #0 app_ImageCache}
05-13 13:26:02.358: V/FragmentManager(7468): movefrom STOPPED: FirstFragment{4077dfa8 #1 id=0x7f04000d}
05-13 13:27:15.219: V/FragmentManager(7468): movefrom RESUMED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:27:15.219: V/FragmentManager(7468): movefrom RESUMED: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:27:15.239: V/FragmentManager(7468): Commit: BackStackEntry{40a8a6d0}
05-13 13:27:15.259: V/FragmentManager(7468): Commit: BackStackEntry{40a90190}
05-13 13:27:15.279: V/FragmentManager(7468): Run: BackStackEntry{40a8a6d0}
05-13 13:27:15.279: V/FragmentManager(7468): add: RetainFragment{40a7fdf0 app_ImageCache}
05-13 13:27:15.279: V/FragmentManager(7468): Allocated fragment index RetainFragment{40a7fdf0 #0 app_ImageCache}
05-13 13:27:15.279: V/FragmentManager(7468): moveto CREATED: RetainFragment{40a7fdf0 #0 app_ImageCache}
05-13 13:27:15.279: V/FragmentManager(7468): moveto ACTIVITY_CREATED: RetainFragment{40a7fdf0 #0 app_ImageCache}
05-13 13:27:15.279: V/FragmentManager(7468): Run: BackStackEntry{40a90190}
05-13 13:27:15.279: V/FragmentManager(7468): add: ThirdFragment{406c2308 id=0x7f04000d}
05-13 13:27:15.279: V/FragmentManager(7468): Allocated fragment index ThirdFragment{406c2308 #1 id=0x7f04000d}
05-13 13:27:15.289: V/FragmentManager(7468): moveto CREATED: ThirdFragment{406c2308 #1 id=0x7f04000d}
05-13 13:27:15.289: V/FragmentManager(7468): moveto ACTIVITY_CREATED: ThirdFragment{406c2308 #1 id=0x7f04000d}
05-13 13:27:15.410: V/FragmentManager(7468): moveto STARTED: RetainFragment{40a7fdf0 #0 app_ImageCache}
05-13 13:27:15.410: V/FragmentManager(7468): moveto STARTED: ThirdFragment{406c2308 #1 id=0x7f04000d}
05-13 13:27:15.430: V/FragmentManager(7468): moveto RESUMED: RetainFragment{40a7fdf0 #0 app_ImageCache}
05-13 13:27:15.430: V/FragmentManager(7468): moveto RESUMED: ThirdFragment{406c2308 #1 id=0x7f04000d}
05-13 13:27:15.810: V/FragmentManager(7468): Saved state of RetainFragment{4076f1b0 #0 app_ImageCache}: null
05-13 13:27:15.810: V/FragmentManager(7468): Saved state of SecondFragment{40713c28 #1 id=0x7f04000d}: Bundle[{android:view_state=android.util.SparseArray@40aa62c0}]
05-13 13:27:15.810: V/FragmentManager(7468): saveAllState: adding fragment #0: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:27:15.810: V/FragmentManager(7468): saveAllState: adding fragment #1: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:27:15.810: V/FragmentManager(7468): movefrom STARTED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:27:15.810: V/FragmentManager(7468): movefrom STARTED: SecondFragment{40713c28 #1 id=0x7f04000d}
05-13 13:27:15.820: V/FragmentManager(7468): movefrom STOPPED: RetainFragment{4076f1b0 #0 app_ImageCache}
05-13 13:27:15.820: V/FragmentManager(7468): movefrom STOPPED: SecondFragment{40713c28 #1 id=0x7f04000d}
// Here I'm waiting for a while to make sure Android has enough time to do anything it wants, then I press a button gorse-closing the app
05-13 13:27:59.783: D/AndroidRuntime(7468): Shutting down VM
05-13 13:28:14.928: V/FragmentManager(7523): Instantiated fragment RetainFragment{406cde80 #0 app_ImageCache}
05-13 13:28:14.938: V/FragmentManager(7523): restoreAllState: active #0: RetainFragment{406cde80 #0 app_ImageCache}
05-13 13:28:14.938: V/FragmentManager(7523): Instantiated fragment FirstFragment{406d8410 #1 id=0x7f04000d}
05-13 13:28:14.938: V/FragmentManager(7523): restoreAllState: active #1: FirstFragment{406d8410 #1 id=0x7f04000d}
05-13 13:28:14.938: V/FragmentManager(7523): restoreAllState: added #0: RetainFragment{406cde80 #0 app_ImageCache}
05-13 13:28:14.938: V/FragmentManager(7523): restoreAllState: added #1: FirstFragment{406d8410 #1 id=0x7f04000d}
05-13 13:28:14.938: V/FragmentManager(7523): moveto CREATED: RetainFragment{406cde80 #0 app_ImageCache}
05-13 13:28:14.938: V/FragmentManager(7523): moveto CREATED: FirstFragment{406d8410 #1 id=0x7f04000d}
05-13 13:28:15.128: V/msm8660.gralloc(7523): PmemUserspaceAllocator::PmemUserspaceAllocator(PmemUserspaceAllocator::Deps&, PmemUserspaceAllocator::Deps::Allocator&, const char*) begin
05-13 13:28:15.138: V/msm8660.gralloc(7523): PmemUserspaceAllocator::PmemUserspaceAllocator(PmemUserspaceAllocator::Deps&, PmemUserspaceAllocator::Deps::Allocator&, const char*) end
05-13 13:28:15.138: V/msm8660.gralloc(7523): PmemKernelAllocator::PmemKernelAllocator(PmemKernelAllocator::Deps&) begin
05-13 13:28:15.138: V/msm8660.gralloc(7523): PmemKernelAllocator::PmemKernelAllocator(PmemKernelAllocator::Deps&) end
05-13 13:28:15.408: V/FragmentManager(7523): moveto ACTIVITY_CREATED: RetainFragment{406cde80 #0 app_ImageCache}
05-13 13:28:15.408: V/FragmentManager(7523): moveto ACTIVITY_CREATED: FirstFragment{406d8410 #1 id=0x7f04000d}
java.lang.RuntimeException: Unable to destroy activity {com.myapp/com.myapp.activity.FirstFragment}: java.lang.NullPointerException
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3272)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3299)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.ActivityThread.access$2100(ActivityThread.java:134)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1143)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.os.Handler.dispatchMessage(Handler.java:99)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.os.Looper.loop(Looper.java:152)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.ActivityThread.main(ActivityThread.java:4606)
05-13 13:35:41.824: E/AndroidRuntime(7691): at java.lang.reflect.Method.invokeNative(Native Method)
05-13 13:35:41.824: E/AndroidRuntime(7691): at java.lang.reflect.Method.invoke(Method.java:491)
05-13 13:35:41.824: E/AndroidRuntime(7691): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
05-13 13:35:41.824: E/AndroidRuntime(7691): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
05-13 13:35:41.824: E/AndroidRuntime(7691): at dalvik.system.NativeStart.main(Native Method)
// see the original question log, it is quite the same
05-13 13:35:41.824: E/AndroidRuntime(7691): Caused by: java.lang.NullPointerException
05-13 13:35:41.824: E/AndroidRuntime(7691): at com.myapp/com.myapp.activity.FirstFragment.onCreateView(FirstFragment.java:41)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.Fragment.performCreateView(Fragment.java:1460)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentManagerImpl.dispatchReallyStop(FragmentManager.java:1888)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentActivity.onReallyStop(FragmentActivity.java:787)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentActivity.doReallyStop(FragmentActivity.java:764)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:322)
05-13 13:35:41.824: E/AndroidRuntime(7691): at com.myapp.activity.FragmentsContainerActivity.onDestroy(FragmentsContainerActivity.java:806)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.Activity.performDestroy(Activity.java:4662)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1113)
05-13 13:35:41.824: E/AndroidRuntime(7691): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3255)
05-13 13:35:41.824: E/AndroidRuntime(7691): ... 11 more
The line #806 of FragmentsContainerActivity
is super.onDestroy();
:
@Override
public void onDestroy() {
try {
unregister(receiver);
} catch (Exception e) {
}
super.onDestroy();
回答1:
As guided in the code sample here referring to the onResume
method You should:
Always call the superclass method first
Meanning you should put your super.onResume();
right at the start.
That must be the problem.
At the current code you are running, you are confusing the FragmentActivity who is being told to stop (i.e. finish
) and then being told to resume
. a life cycle which is not "legit" in the activity life cycle.
The fragments are affected directly by that because their life cycle is invoked from the activity life cycle, and if the activity went from finishing -> resume it can sure mean that the fragments went from finishing/destroy -> resuming (going through onCreateView).
回答2:
Without seeing the code, we can't help you with the specific problem at hand. For one, though, the fact that it's a DialogFragment is irrelevant.
That said, in my experience, FragmentManager.enableDebugLogging()
is a life-saver when you're having trouble with the lifecycles. It would, for example, tell you what that last moveToState does (i.e., what states it's moving between), which might shed some light on the bug.
回答3:
For your specific problem did you try calling the super.resume() before calling finish() ?
Otherwise you should look at the source code: https://github.com/mastro/android-support-library-archive/blob/23ad71b245e7b7bbde6a501671ab411725ce16f5/v4/src/java/android/support/v4/app/FragmentManager.java
From this stacktrace line android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
回答4:
Please see this similar question, which describes the same behavior that you're seeing, but the solution probably doesn't apply in your case. To fix your issue, you could simply check if anything that your code is relying on in onCreateView
is null
.
来源:https://stackoverflow.com/questions/14866854/why-is-dialogfragment-oncreateview-called-when-activity-is-being-destroyed