Фрагмент - InstantationException: нет пустого конструктора → Google Maps v2?

Я получаю это сообщение об ошибке, когда я снова открываю закрытое приложение с помощью кнопки App-Change:

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

Я нашел несколько советов о Inner-Classes и сделал их статичными и т.д. Но этот FragmentContact является общедоступным классом в *. java файле и имеет открытый пустой конструктор. Я использую Google Maps Api v2 в этом проекте и делаю трюк где-то из Интернета, чтобы настроить MapView. Смотрите здесь:

@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;

    }

Когда я режу эту вещь MapView, все работает нормально. Может быть, кто-то может объяснить, что я делаю неправильно.

Моя полная Stacktrace:

04-17 16:15:22.115: E/AndroidRuntime(22182): FATAL EXCEPTION: main
04-17 16:15:22.115: E/AndroidRuntime(22182): 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
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2307)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2357)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.ActivityThread.access$600(ActivityThread.java:153)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.os.Looper.loop(Looper.java:137)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.ActivityThread.main(ActivityThread.java:5226)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at java.lang.reflect.Method.invokeNative(Native Method)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at java.lang.reflect.Method.invoke(Method.java:511)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at dalvik.system.NativeStart.main(Native Method)
04-17 16:15:22.115: E/AndroidRuntime(22182): 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
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.support.v4.app.Fragment.instantiate(Fragment.java:405)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.support.v4.app.FragmentState.instantiate(Fragment.java:97)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1767)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:208)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at com.*.MainActivity.onCreate(MainActivity.java:20)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.Activity.performCreate(Activity.java:5104)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2261)
04-17 16:15:22.115: E/AndroidRuntime(22182):    ... 11 more
04-17 16:15:22.115: E/AndroidRuntime(22182): Caused by: java.lang.InstantiationException: can't instantiate class com.*.FragmentContact$1; no empty constructor
04-17 16:15:22.115: E/AndroidRuntime(22182):    at java.lang.Class.newInstanceImpl(Native Method)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at java.lang.Class.newInstance(Class.java:1319)
04-17 16:15:22.115: E/AndroidRuntime(22182):    at android.support.v4.app.Fragment.instantiate(Fragment.java:394)
04-17 16:15:22.115: E/AndroidRuntime(22182):    ... 18 more

Ответ 1

Но этот FragmentContact является открытым классом в *.java файле и имеет открытый пустой конструктор.

Ошибка не жалуется на FragmentContact. Он жалуется на первый внутренний класс FragmentContact (FragmentContact$1). Вы не можете использовать Fragment как внутренний класс чего-либо, поскольку он не может быть создан извне внешнего класса. Внутренний класс static отлично.

Ответ 2

У меня была эта проблема целую вечность, и, наконец, комментарии здесь решили ее для меня. Хорошая информация о $1 означает анонимный внутренний класс.

Переместите инициализацию карты в новый Открытый класс, например. MyMapFragment.java. Это позволит создать экземпляр фрагмента без экземпляра

Для тех, кто еще не знает, как это исправить. Напишите код следующим образом (используя примерный код из исходного вопроса):

//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;
}
....

Создайте новый MyMapFragment.java, чтобы он больше не был внутренним классом. Это позволит создать фрагмент без его внешнего класса.

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);
        }
    }
}    

Создайте MapLoadedCallback.java, чтобы вы могли обрабатывать, когда карта закончила загрузку, и получить экземпляр загруженного объекта карты

public interface MapLoadedCallback {
    void onLoaded(GoogleMap map);
}

Ответ 3

  private Entity mEntity;
  public YourFragment() {}
  public static YourFragment getInstance(Entity mEntity) {
    YourFragment fragment = new YourFragment();
    fragment.mEntity = mEntity;
    return fragment;
  }

когда вы используете этот фрагмент, просто вызовите статический метод getInstance.