Recently, in doing a project. When the app launches, then it goes into the background process (press the Home key), and then uses the other app (the other app is designed to keep the system out of memory and then let the system kill our app). When our app is killed by the system, click on our app to access the app via mission management. This time the problem arises, the app crashes, in order not to expose the project, some project package name or class name information is omitted, the following is the key information of the exception:
Java.lang.RuntimeException:Unable to start Activity componentinfo{omitted}: android.support.v4.app.fragment$ Instantiationexception:unable to instantiate fragment omitted $3:make sure class name exists, was public, and have an empty const Ructor that Ispublicat android.app.ActivityThread.performLaunchActivity (activitythread.java:1750) at Android.app.ActivityThread.handleLaunchActivity (activitythread.java:1766) at Android.app.ActivityThread.handleRelaunchActivity (activitythread.java:2960) at android.app.ActivityThread.access $1600 (activitythread.java:127) at Android.app.activitythread$h.handlemessage (activitythread.java:945) at Android.os.Handler.dispatchMessage (handler.java:99) at Android.os.Looper.loop (looper.java:130) at Android.app.ActivityThread.main (activitythread.java:3818) at java.lang.reflect.Method.invokeNative (Native Method) At Java.lang.reflect.Method.invoke (method.java:507) at Com.android.internal.os.zygoteinit$methodandargscaller.run (zygoteinit.java:875) at Com.android.internal.os.ZygoteInit.main (zygoteinit.java:633) at Dalvik.system.NativeStart.main (Native Method) caused by:android.support.v4.app.fragment$ Instantiationexception:unable to instantiate fragment omitted $3:make sure class name exists, was public, and have an empty cons Tructor thatis publicat android.support.v4.app.Fragment.instantiate (fragment.java:399) at Android.support.v4.app.FragmentState.instantiate (fragment.java:97) at Android.support.v4.app.FragmentManagerImpl.restoreAllState (fragmentmanager.java:1760) at Android.support.v4.app.FragmentActivity.onCreate (fragmentactivity.java:200) at ellipsis at Android.app.Instrumentation.callActivityOnCreate (instrumentation.java:1047) at Android.app.ActivityThread.performLaunchActivity (activitythread.java:1710) ... Morecaused By:java.lang.instantiationexception:com.redacted.redacted.preferencelistfragment$3at Java.lang.Class.newInstanceImpl (Native Method) at Java.lang.Class.newInstance (class.java:1409) at Android.support.v4.app.Fragment.instantiate (fragment.java:388) ... More
From the key information above, it can be seen that the reason for the exception is because the fragment used does not have a public empty constructor. Fact, and indeed, my fragment has a parameter constructor but I have no public empty constructor.
Then the question comes, why fragment must be empty constructor?
First see this exception stack, you can find the problem is because, Fragment in the Restore state call Fragmentstate#instantitae ()->fragment#instantitae () throws an exception, then along this call point, Enter the source code.
First, look at the key code slices for the Fragmentstate
Public Fragment Instantiate (fragmentactivity activity, Fragment Parent) {if (minstance! = null) {Retu RN Minstance; } if (marguments! = null) {Marguments.setclassloader (Activity.getclassloader ()); } minstance = Fragment.instantiate (activity, Mclassname, marguments); if (msavedfragmentstate! = null) {Msavedfragmentstate.setclassloader (Activity.getclassloader ()); Minstance.msavedfragmentstate = msavedfragmentstate; } Minstance.setindex (Mindex, parent); Minstance.mfromlayout = Mfromlayout; Minstance.mrestored = true; Minstance.mfragmentid = Mfragmentid; Minstance.mcontainerid = Mcontainerid; Minstance.mtag = Mtag; Minstance.mretaininstance = mretaininstance; minstance.mdetached = mdetached; Minstance.mfragmentmanager = activity.mfragments; if (fragmentmanagerimpl.debug) log.v (Fragmentmanagerimpl.tag, "Instantiated fragment" + minstance); return minstance; }Obviously, in the above code slice, the method call Minstance = Fragment.instantiate (activity, Mclassname, marguments) was found at one glance, and you guessed it, it is the Fragment instance object assignment. Along this point into the fragment#instantiate (),
/** * Create A new instance of a Fragment with the given class name. This was * the same as calling its empty constructor. * * @param context The calling context being used to instantiate the fragment. * This was currently just used to get the its ClassLoader. * @param fname The class name of the fragment to instantiate. * @param args Bundle of arguments to supply to the fragment, which it * can retrieve with {@link #getArguments ()}. May is null. * @return Returns a new fragment instance. * @throws Instantiationexception If There is a failure in instantiating * the given fragment class. This is a runtime exception; It is not * normally expected to happen. */public static Fragment instantiate (context context, String fname, Bundle args) {try {class<?& Gt Clazz = Sclassmap.get (fname); if (clazz = = null) {//Class not found in the cache, see if it's real, and try to add it Clazz = Context.getclassloader (). LoadClass (fname); Sclassmap.put (fname, clazz); } Fragment F = (Fragment) clazz.newinstance (); if (args! = null) {Args.setclassloader (F.getclass (). getClassLoader ()); f.marguments = args; } return F; } catch (ClassNotFoundException e) {throw new Instantiationexception ("Unable to instantiate fragment" + fname + ": Make sure class name exists, was public, and have a" + "empty constructor that Is public ", e); } catch (Java.lang.InstantiationException e) {throw new Instantiationexception ("Unable to instantiate fragment "+ fname +": Make sure class name exists, are public, and have an "+" empty Constr Uctor that's public ", e); } catch (Illegalaccessexception e) {throw new Instantiationexception ("Unable to instantiate fragment"+ fname + ": Make sure class name exists, are public, and have an" + "empty construct Or that's public ", e); } }From its catch statement block, it can also be seen, is not exactly the same as the previous exception information. Exception throwing is really from this, the key of the above code slice, in fact, is through the Java reflection mechanism to instantiate fragment. Well, it doesn't matter if you don't know much about the Java reflection mechanism, just follow the idea. where Fragment f = (Fragment) clazz.newinstance () is the key, first look at the Java doc of Class#newinstance (),
Public T newinstance () throws Instantiationexception, Illegalaccessexception Create s a new instance of the class represented by this class object. The class is instantiated as if-a new expression with an empty argument list. The class is initialized if it have not already been initialized. Note that this method propagates any exception thrown by the Nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise is performed by the Compi Ler. The Constructor.newinstance method avoids this problem by wrapping all exception thrown by the Constructor in a (checked) Invocationtargetexception.returns:a newly allocated instance of the class represented by this object. Throws:illegalaccessexception-if the class or its nullary constructor are not accessible. Instantiationexception-if This class represents a abstract Class, an interface, an ARRay class, a primitive type, or void; Or if the class has no nullary constructor; Or if the instantiation fails for some and other reason. Exceptionininitializererror-if the initialization provoked by this method fails. Securityexception-if a security manager, S, is present and any of the following conditions is met:invocation of s.checkm Emberaccess (this, member.public) denies creation of new instances of this classthe caller ' s class loader are not the same a s or an ancestor of the class loader for the current class and invocation of S.checkpackageaccess () denies access to the P Ackage of this class
The key message for us is to look at Instantiationexception and illegalaccessexception:
- Instantiationexception, if the class does not have an empty constructor, the exception is thrown.
- Illegalaccessexception, if the class does not have a public empty constructor, the exception is thrown.
At this point, why fragment need the public of the empty constructor, the answer is vividly on. To support this analysis, a description of the Fragment API document is found,
Public Fragment () Default constructor. Every fragment must has an empty constructor and so it can is instantiated when the restoring its activity's state. It is strongly recommended that subclasses does not has other constructors with parameters, since these constructors would n OT be called if the fragment is re-instantiated; Instead, arguments can be supplied by the caller with Setarguments (Bundle) and later retrieved by the Fragment with Getarg Uments (). Applications should generally not implement a constructor. The first place application code a run where the fragment is a ready-to-be used are in Onattach (Activity) and the point where t He fragment is actually associated with its activity. Some applications may also want to implement Oninflate (Activity, AttributeSet, bundles) to retrieve attributes from a layou t resource, though should take care here because this happens for the fragment are attached to its activity.
An analysis of why fragment needs the public's empty constructor