java.lang.InstantiationException: can't instantiate class … no empty constructor

浪尽此生 提交于 2019-12-07 10:33:07

问题


I have found topics with similar questions like mine but cant find the answer I am looking for so far. my application consists of a FragmentActivity which hosts a ViewPagerAdapter (child of FragmentPagerAdapter) with a fragment in each tab. My ViewPagerAdapter is instantiated in the OnCreateView function of the parent activity

_adapter = new ViewPagerAdapter(getApplicationContext()
                         , getSupportFragmentManager()
                         , numOfTabs
                         , status);

The ViewPagerAdapter implements the minimum required methods getItem, getCount and getItemPosition

My getItem initializes a different Fragment for each position:

    @Override
public Fragment getItem(int position) 
{
    Fragment f = new Fragment();
    Log.d("Adbox",String.format("Inside ViewPagerAdapter.getItem(%s)",position));

    switch(position)
    {
        case 0:
            Log.d("Adbox","All offers  ==");
            f=FragmentAllOffers.newInstance(_context);
            f.setRetainInstance(true);
            break;
        case 1:
            Log.d("Adbox","Nearby offers  ==");
            f=FragmentNearbyOffers.newInstance(_context);
            //f.setRetainInstance(true);
            break;
        case 2:
            Log.d("Adbox","My coupons  ==");
            f=FragmentCoupons.newInstance(_context);
            f.setRetainInstance(true);
            break;
        case 3:
            Log.d("Adbox","Account  ==");
            f=FragmentAccount.newInstance(_context);
            f.setRetainInstance(true);
            //f=LayoutLocal.newInstance(_context);  
            break;
        case 4:
            Log.d("Adbox","Preferences  ==");
            f=FragmentPreferences.newInstance(_context);
            f.setRetainInstance(true);
            break;
        default:
            break;
    }
    return f;
}

The call to setRetainInstance(true) was added in my effort to resolve the problem I am facing but hasn't helped either.

Finally each of the Fragments above implement a public static newInstance() function with the application context as argument. For example the FragmentNearbyOffers contains the following:

    public static android.support.v4.app.Fragment newInstance(Context ctx)
{
    FragmentNearbyOffers f = new FragmentNearbyOffers();
    ctx = context;
    //Bundle bdl = new Bundle();
    return f;
}

One more important information is that the parent activity is declared as singleInstance and I would like to keep this like this for some reasons.

Everything works fine but at some point when the activity is in the background for some time and I try to return to it either via the TaskManager or by clicking on the application icon I get the exception

android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1: make sure class name exists, is public, and has an empty constructor that is public

The class name definitely exists, it's public and doesn't have a constructor which is like having an empty one.. I even added an empty constructor explicitly but this didn't help either, although I verified it is called.

From what I understood from various posts here is that Android when resuming the application, is placing in the FragmentPagerAdapter new instances of the fragments that are not linked to the original activity.. I verified this also because when calling the getActivity from inside the fragment I receive null.. But I don't understand why I am getting this Exception since there is an empty constructor... I don't even know where to fix this, since the execution enters the onCreate of the activity, then immediately goes into the empty constructors of the fragments and then I get the exception.. Any other methods of the fragments i.e. onAttach, onCreate etc are not called at all..So it seems like it's actually crashing when constructing the fragments..

I am attaching the whole stacktrace I am getting just in case it helps:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.advisor/com.advisor.AdBoxWidgetConfigurationFragment}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1: make sure class name exists, is public, and has an empty constructor that is public
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
    at android.app.ActivityThread.access$700(ActivityThread.java:140)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4921)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1: 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.advisor.AdBoxWidgetConfigurationFragment.onCreate(AdBoxWidgetConfigurationFragment.java:60)
    at android.app.Activity.performCreate(Activity.java:5206)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
    ... 11 more
 Caused by: java.lang.InstantiationException: can't instantiate class com.advisor.FragmentNearbyOffers$1; no empty constructor
    at java.lang.Class.newInstanceImpl(Native Method)
    at java.lang.Class.newInstance(Class.java:1319)
    at android.support.v4.app.Fragment.instantiate(Fragment.java:388)

回答1:


Notice the $1 at the end of the error. This is a reference to an anonymous class, not the fragment named FragmentNearbyOffers:

Unable to instantiate fragment com.advisor.FragmentNearbyOffers$1

Since fragments require a default constructor, and anonymous classes can never provide one, fragments must always be a named class. The Java Language Specification, section 15.9.5.1 states:

An anonymous class cannot have an explicitly declared constructor.

This section also explains that constructors are generated automatically, according to the context in which the anonymous class is declared. All of these constructors have parameters, thus they have a different signature than the default constructor. The combined effect is that anonymous classes can never have a constructor that matches the default constructor's signature.

You can either declare the fragment class in it's own file or declare it as a static nested class:

  public static class NestedFragment extends BaseFragment { ...

Both of those methods should work just fine.




回答2:


I managed to resolve the problem.. It was quite a tricky one because the exception message was misleading. Inside my fragment I had another nested fragment which I created in runtime with an inner class.

        mMapFragment = new SupportMapFragment()
    {
        @Override
        public void onResume()
        {
            // TODO Auto-generated method stub
            super.onResume();
            //initMap();
        }

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

            map = mMapFragment.getMap();
            if (map != null)
            {
                // map.setMapType(GoogleMap.MAP_TYPE_NONE);
                map.setMyLocationEnabled(true);
                CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(lat, lng));
                zoom = CameraUpdateFactory.zoomTo(18);
                map.moveCamera(center);
                map.animateCamera(zoom);
            }

        }
    };

Since after the application is killed by Android, when resuming back to it, android recreates the fragments and I am guessing that it couldnt recreate the nested one because the constructor of the inner class was not visible. I moved the class to a separate file as suggested in some other posts and it worked.



来源:https://stackoverflow.com/questions/16464645/java-lang-instantiationexception-cant-instantiate-class-no-empty-construct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!