17

I get this error message, when I open a closed App again via App-Change button:

Caused by: java.lang.InstantiationException: can't instantiate class com.*.FragmentContact$1; no empty constructor

I've found several tips about Inner-Classes and to make them static etc. But this FragmentContact is a public class in a *.java-file and has a public empty constructor. I'm using Google Maps Api v2 in this project and do a trick somewhere from the internet to setup my MapView. Look here:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_contact, null);

    try {
        MapsInitializer.initialize(this.getActivity().getApplicationContext());
    } catch (GooglePlayServicesNotAvailableException e) {
        e.printStackTrace();
    }

    fragment = new SupportMapFragment() {
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            mMap = fragment.getMap();
            if (mMap != null) {
                setupMap();
            }
        }
    };

    getFragmentManager().beginTransaction().replace(R.id.fragment_orte_map_parent, fragment).commit();

    return v;
}

When I cut this MapView-thing out everything work fine. Maybe someone can explain what I'm doing wrong.

My complete Stacktrace:

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.*/com.*.MainActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.*.FragmentContact$1: make sure class name exists, is public, and has an empty constructor that is public
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2307)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2357)
   at android.app.ActivityThread.access$600(ActivityThread.java:153)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:5226)
   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:795)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.*.FragmentContact$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:405)
   at android.support.v4.app.FragmentState.instantiate(Fragment.java:97)
   at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1767)
   at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:208)
   at com.*.MainActivity.onCreate(MainActivity.java:20)
   at android.app.Activity.performCreate(Activity.java:5104)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2261)
   ... 11 more
Caused by: java.lang.InstantiationException: can't instantiate class com.*.FragmentContact$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:394)
   ... 18 more
stkent
  • 19,772
  • 14
  • 85
  • 111
Osiriz
  • 218
  • 1
  • 2
  • 15

4 Answers4

32

But these FragmentContact is a public class in a *.java-file and has a public empty constructor.

The error is not complaining about FragmentContact. It is complaining about the first inner class of FragmentContact (FragmentContact$1). You cannot have a Fragment implemented as an inner class of anything, as it cannot be instantiated from outside the outer class. A static inner class is fine.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    Sorry, my fault. I didn't recognize the anonymous inner class because I've thought about non-anonymous inner classes all the time. You're absolutely right. I override the `public void onActivityCreated(Bundle savedInstanceState)` and so i use an anonymous inner class. Shame on me... – Osiriz Apr 18 '13 at 12:21
  • 5
    @Osiriz: The `$1` means that it is an anonymous inner class -- otherwise, it would have been `$WhateverYouCalledTheInnerClass`. That being said, I missed it when originally reading your code, thinking that it was in some other file. – CommonsWare Apr 18 '13 at 12:26
  • 3
    I have to confess, that I didn't even know the meaning of `$1` in the stacktrace till now. Many tanks! – Osiriz Apr 18 '13 at 12:43
  • Hello, I am facing the same issue... I don't really understand the explanations, and how to fiw it.. What was the easiest way to avoid this problem? – Waza_Be Jun 19 '13 at 12:33
  • 2
    @Waza_Be: Do not create fragments as regular (non-static) inner classes. They need to be a static inner class or a regular (standalone) Java class. – CommonsWare Jun 19 '13 at 12:40
  • The fragment I instanciated is a MapFragment so, a regular (standalone) class, isn't it? – Waza_Be Jun 19 '13 at 12:48
  • @Waza_Be: If you literally mean `MapFragment`, yes. If you mean some subclass you created of `MapFragment`, perhaps not. – CommonsWare Jun 19 '13 at 13:00
  • can you show the fix.. i have the same issue and am not understanding the innerclass stuff – erik Apr 25 '14 at 11:32
  • you mean the `SupportMapFragment` *instance* should be static! – Muhammad Babar Oct 13 '14 at 07:46
  • i read the comments still didn't understand. This thing is new for me.This is what i'm doing inside my class HomeFragment i.e extending Fragment. `mapFragment = new SupportMapFragment() { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mapView = mapFragment.getMap(); mapView.setMapType(GoogleMap.MAP_TYPE_SATELLITE); }; };` I have also made the `mapFragment` static but error presists. – Muhammad Babar Oct 13 '14 at 07:57
  • @CommonsWare can you please explain the solution, since I do not seem to understand it – Menelaos Kotsollaris Mar 11 '15 at 01:38
0

I've had this issue for ages and finally the comments on here have solved it for me. Nice information about the $1 meaning anonymous inner class.

Move your map initialisation to a new Public Class, e.g. MyMapFragment.java. This will allow the fragment to be instantiated without the instance of

For those still not sure how to fix it. Write the code as follows (using the example code from the original question):

//Existing code to instantiate map
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View v = inflater.inflate(R.layout.fragment_contact, null);

    try {
        MapsInitializer.initialize(this.getActivity().getApplicationContext());
    } catch (GooglePlayServicesNotAvailableException e) {
        e.printStackTrace();
    }

    fragment = new MyMapFragment();

    //added callback for catching when the map has finished loading
    mapFragment.setLoadedCallback(new MapLoadedCallback() {
        @Override
        public void onLoaded(GoogleMap map) {
            mMap = map;
        }
    });

    getFragmentManager().beginTransaction().replace(R.id.fragment_orte_map_parent, fragment).commit();

    return v;
}
....

Create new MyMapFragment.java so that it is no longer an inner class. This will allow the fragment to be created without it's outer class.

public class MyMapFragment extends SupportMapFragment 
{
    GoogleMap mMap;
    public MyMapFragment() {
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
         mMap = fragment.getMap();
         if (mMap != null) {
             mCallback.onLoaded(mMap);
        }
    }
}    

Create MapLoadedCallback.java to allow you to handle when the map has finished loading and to retrieve an instance of the loaded map object

public interface MapLoadedCallback {
    void onLoaded(GoogleMap map);
}
Matthew Cawley
  • 2,828
  • 1
  • 31
  • 42
  • It will not help... as this is not static inner class... The only difference is that this one is not anonymous... – Selvin Feb 18 '16 at 03:10
  • @Selvin : I'm not sure what you mean. The issue is resolved due to the fact that the class is no longer anonymous. If it was static the issue wouldn't have existed in the first place as a static inner class could have been resolved correctly. – Matthew Cawley Feb 22 '16 at 12:19
  • inner non static class still doesn't has no empty constructor (outside the outer class scope) ... you cannot call `new Outer.Inner()` (yes, you can call `new Inner()` inside `Outer` `Fragment.instantiate`can't do this) -- in other words: java's basics ... inner non static class instance cannot be initialized without outer class instance – Selvin Feb 22 '16 at 12:21
  • Yes, I get you now. I made changes to the way I implemented after writing my answer. I will update this code to match what I have. Thank you for point this out. Give me a few minutes to update my answer – Matthew Cawley Feb 22 '16 at 12:27
  • I have updated my answer, I hope this is better now. Thanks again @Selvin for point this out – Matthew Cawley Feb 22 '16 at 12:37
0
  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.

stuckoverflow
  • 625
  • 2
  • 7
  • 23
Vikram
  • 11
  • 1
-3
  private Entity mEntity;
  public YourFragment() {}
  public static YourFragment getInstance(Entity mEntity) {
    YourFragment fragment = new YourFragment();
    fragment.mEntity = mEntity;
    return fragment;
  }

when you use this fragment,just call the static method getInstance.

Eric
  • 330
  • 2
  • 9