1

I have a Fragment which calls setRetainInstance(true), such that it is not recreated on orientation changes. It does not have a public empty constructor. I was under the impression that the framework would never (re)create fragments that have setRetainInstance(true) applied to them, However, I have received exceptions stating that it is being created:

java.lang.RuntimeException: Unable to start activity ComponentInfo{<foo>/<foo>.Activity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment <foo>.SomeFragment: make sure class name exists, is public, and has an empty constructor that is public
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2063)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
       at android.app.ActivityThread.access$600(ActivityThread.java:134)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:4744)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment <foo>.SomeFragment.d: make sure class name exists, is public, and has an empty constructor that is public
       at android.app.Fragment.instantiate(Fragment.java:588)
       at android.app.FragmentState.instantiate(Fragment.java:97)
       at android.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1732)
       at android.app.Activity.onCreate(Activity.java:883)
       at <foo>.Activity.onCreate(SourceFile:57)
       at android.app.Activity.performCreate(Activity.java:5008)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2027)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
       at android.app.ActivityThread.access$600(ActivityThread.java:134)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:4744)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: java.lang.InstantiationException: cannot instantiate class <foo>.SomeFragment; no empty constructor
       at java.lang.Class.newInstanceImpl(Class.java)
       at java.lang.Class.newInstance(Class.java:1319)
       at android.app.Fragment.instantiate(Fragment.java:577)
       at android.app.FragmentState.instantiate(Fragment.java:97)
       at android.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1732)
       at android.app.Activity.onCreate(Activity.java:883)
       at <foo>.Activity.onCreate(SourceFile:57)
       at android.app.Activity.performCreate(Activity.java:5008)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2027)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
       at android.app.ActivityThread.access$600(ActivityThread.java:134)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:4744)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
       at dalvik.system.NativeStart.main(NativeStart.java)

My question is twofold:

  1. In which cases do the Android framework create these fragments? I have a hunch that it is when an Activity is closed, garbage collected and later opened.
  2. Would I fix the bug, as seen in the exception report above, by passing arguments to the fragment using bundles? (as seen in an answer to "Do fragments really need an empty constructor?")
Community
  • 1
  • 1
foens
  • 8,642
  • 2
  • 36
  • 48

1 Answers1

0

In which cases do the Android framework create these fragments? I have a hunch that it is when an Activity is closed, garbage collected and later opened.

Close. This scenario would occur if Android terminates your process (e.g., user pressed HOME, and time passed), then the user attempts to return to your app in a way that would lead the user back to this previous activity instance (e.g., recent-tasks list).

Would I fix the bug, as seen in the exception report above, by passing arguments to the fragment using bundles?

Probably. The Bundle will part of the saved instance state, and so you will have access to the Bundle with your saved data even in this situation. I say "probably" only because you have not indicated what you are passing into the fragment constructor, and a Bundle cannot hold onto arbitrary objects. Some objects (e.g., a Socket) cannot be saved this way.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I used the developer option `Don't keep activities` on my phone to reach the error condition. Turn it on, then get the Fragment to show and leave the activity. The activity is destroyed. Now enter it again using the recent-tasks list and then the application should crash. – foens May 10 '14 at 12:07