简体   繁体   中英

Android InstantiationException With Fragment (It Is Public)

I have a Fragment (it is not an inner class, and it does not have any constructor whatsoever)

public class PreferenceListFragment extends ListFragment implements OnClickListener

I'm getting this crash report on the Android Developer Console:

java.lang.RuntimeException: Unable to start activity 
ComponentInfo{com.redacted.redacted/com.redacted.redacted.PreferenceActivity}: 
android.support.v4.app.Fragment$InstantiationException: 
Unable to instantiate fragment com.redacted.redacted.PreferenceListFragment$3:
make sure class name exists, is public, and has an empty constructor that is
public
at 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 com.redacted.redacted.PreferenceListFragment$3: 
make sure class name exists, is public, and has an empty constructor that
is public
at 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 com.redacted.redacted.PreferenceActivity.onCreate(PreferenceActivity.java:37)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1710)
... 12 more
Caused by: java.lang.InstantiationException: 
com.redacted.redacted.PreferenceListFragment$3
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1409)
at android.support.v4.app.Fragment.instantiate(Fragment.java:388)
... 18 more

I am unable to replicate this on any of my test devices.

Here's the PreferenceActivity.onCreate where the exception is occurring:

public class PreferenceActivity extends FragmentActivity{

    PreferenceListFragment frag;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.preference);

        frag = (PreferenceListFragment) getSupportFragmentManager().
                findFragmentById(R.id.preference_list_frag);
        frag.setState(AlarmPreferenceState.Selected);
        frag.setIsTwoPane(false);
    }

    .
    .
    .
}

And here is R.layout.preference :

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment class="com.redacted.redacted.PreferenceListFragment"
          android:id="@+id/preference_list_frag"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>

</FrameLayout>

Anyone know why I might be getting this exception, and/or how to reproduce it?

You MUST have an empty public constructor. Whoever told you to not have a fragment constructor steered you in the wrong direction.

What they might have told you, is to not have a constructor that accepts arguments, since those may not be called by the system when re-creating the fragments. In that case, use the example in the docs to supply arguments to your fragment.

Quoted from the docs :

All subclasses of Fragment must include a public empty constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the empty constructor is not available, a runtime exception will occur in some cases during state restore. [1], [2]

[1] : https://developer.android.com/reference/android/app/Fragment.html

[2] : https://developer.android.com/reference/android/app/Fragment.html#Fragment()

CHECK YOUR PROGUARD RULES

The strange thing in my case was, this error popped only in the release build and not in the debug build.

The issue was, I was using a FragmentContainerView to hold the Fragment and mentioned the Fragment class name in the XML itself, like this

<androidx.fragment.app.FragmentContainerView
                android:id="@+id/f_navigation_fragment"
                class="com.example.MyFragmentClass"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

This worked fine in the Debug build (without Proguard Obfuscation) but in the Release build (with Proguard Obfuscation) the actual Fragment class was Obfuscated and hence the XML was unable to locate it leading to OP's error.

Please refer this link for additional references.

当我不小心尝试导航到abstract Fragment 类时出现此错误。

1.Ideally we shouldn't pass anything in the fragment constructor, fragment constructor should be empty or default.

2.Now the second question is, what if we want to pass interface variable or parameters-

a. we should use Bundle to pass data.

b.For Interface we can putParceble in bundle and make that interface implement parceble

c. If possible we can implement that interface in activity and in fragment we can initialize listener in OnAttach where we have context[ (context) Listener].

So that during configuration change ex. Font change, Activity recreation listener won't go uninitialize and we can avoid null pointer exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM