Failure saving state: active SupportMapFragment{} has cleared index: -1
Asked Answered
S

3

6

I am using supportMapFragment inside fragment this why I am using this.getChildFragmentManager() if this wrong please guide me

public static ClinicFragment newInstance() {
        ClinicFragment fragment = new ClinicFragment();
        return fragment;
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        setTargetFragment(null , -1); // one of my tries 
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_maps, null, false);

        Log.i(TAG , "onCreateView");

        mapFragment = (SupportMapFragment) this.getChildFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        mapUtils = new MapUtils(getActivity());
        .......
        return view;
    }


 @Override
    public void onMapReady(com.google.android.gms.maps.GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMyLocationEnabled(true);
        mMap.getUiSettings().setZoomControlsEnabled(true);
        mMap.setOnMarkerClickListener(this);
    }

@Override
public void onPause() {
    super.onPause();
    mapUtils.removeUpdate(mMap); // this helper class handle change location listener   
    Log.i(TAG, "onPause");
}
@Override
public void onDestroyView() {
    super.onDestroyView();
    Log.i(TAG, "onDestroyView");

}

@Override
public void onStop() {
    super.onStop();
    Log.i(TAG, "onStop");

    killOldMap();
}

//remove map fragment when view disappeared
private void killOldMap() {
    try{
        SupportMapFragment mapFragment = ((SupportMapFragment) getChildFragmentManager()
                .findFragmentById(R.id.map));
        if(mapFragment != null) {
            FragmentManager fM = getFragmentManager();
            fM.beginTransaction().remove(mapFragment).commit();
        }
    }catch (Exception e){
        e.printStackTrace();

    }

}

My Log

java.lang.IllegalStateException: Failure saving state: active SupportMapFragment{1ba0fd93} has cleared index: -1
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1824)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:2111)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1767)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1835)
at android.support.v4.app.FragmentController.saveAllState(FragmentController.java:125)
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:523)
at android.app.Activity.performSaveInstanceState(Activity.java:1297)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1272)
at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:3923)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3334)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3390)
at android.app.ActivityThread.access$1100(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

I can describe my error that it try remove map fragment but he cant find it reference

My Tries

1- After long research I found setTargetFragment(null , -1); method .

2- Kill fragment in onStop .

but all this tries dont help me to fix my issue , any one can guide me why I miss

Skulduggery answered 27/12, 2015 at 12:34 Comment(1)
You can not change whole question, specially when someone spend time and effort on your question.please take a look at this meta.#290797Prolocutor
V
4

I do not use public static ClinicFragment newInstance()

I use fragments that are attached to activities example.

public class MyFragment extends Fragment 

I do not understand why you are killing off your map fragment. I've never had the need to do this, and just allowed the natural activity lifecycle manage the destruction of of most things.

You are also calling the super method onDestroy before your killOldMap, which means the order of tasks destroyed within the super method will be called before the killOldMap method. This can also leave resources dangling without an attached activity.

Override
public void onStop() {
    super.onStop();
    Log.i(TAG, "onStop");

    killOldMap();
}

So there are a couple of ways to manage this:

Removing the fragment will cause the fragment to be destroyed, without the need to use your kill method:

getActivity().getSupportFragmentManager().beginTransaction().remove(this)
                .commit();

The there's using fragmentTransaction.replace(R.id.yourId, fragment)

Personally I like the idea of using a framelayout within my activity layout and then toggling the visibility between the map and the other fragment, I do not destroy the map, it's there to come back to with whatever co-ordinates I am seeking. This does no harm if I managing the location services well. This is a design choice I use and by no means law.

I manage any location calls with the visibility of the fragments within that framelayout. Creating a custom method:

public void hideFrames() {
    frameLayout2.setVisibility(View.GONE);
    frameLayout3.setVisibility(View.GONE);
}

This way the framelayout manages the visibility of the map.

<RelativeLayout .../...
            android:id="@+id/main">

    <TextView
        android:id="@+id/t1"
    .../.../>


    <FrameLayout
        android:id="@+id/framelayout1"
        android:layout_below="@+id/t1"
        android:layout_height="fill_parent"
        android:layout_width="match_parent"
        android:visibility="gone"/>
    <FrameLayout
        android:id="@+id/framelayout2"
        android:layout_below="@+id/t1"
        android:layout_height="fill_parent"
        android:layout_width="match_parent"
        android:visibility="gone">

        <fragment
            android:id="@+id/map"
            android:layout_height="fill_parent"
            android:layout_width="match_parent"
            android:name="com.google.android.gms.maps.MapFragment"/>
    </FrameLayout>
</RelativeLayout>

and you can have your methods in your parent activity and call them from your fragments:

public void replaceFragment(Fragment fragment) {
    hideFrames();
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.YourId, fragment);
    fragmentTransaction.commit();
}

and it is called from each fragment attached to the activity like so:

// create new fragment
((MainActivity) getActivity()).replaceFragment(fragment);

Also:

There's a known issue with this

Fix issue #6584942 IllegalStateException: Failure saving state...

...active SuggestFragment{419494f0} has cleared index: -1

There were issues when the same fragment was removed and then added again before completely finishing the remove (such as due to a running animation).

Villalba answered 2/1, 2016 at 11:5 Comment(1)
Thank you for answer , but I update my question this may be more clear nowSkulduggery
U
0

For the ones who want more information about that crash. There are confusions between getActivity().getSupportFragmentManager() / getChildFragmentManager() / getFragmentManager().

getActivity().getSupportFragmentManager() is the Activity FragmentManager. getChildFragmentManager() is my FragmentManager (my as the current Fragment) getFragmentManager() is my host FragmentManager (my as the current Fragment) and so my ParentFragment FragmentManager if ParentFragment not null, or my Activity FragmentManager.

So be sure to always use the same FragmentManager.

In the question, we can read:

mapFragment = (SupportMapFragment) this.getChildFragmentManager() .findFragmentById(R.id.map);

And

SupportMapFragment mapFragment = ((SupportMapFragment) getChildFragmentManager() .findFragmentById(R.id.map)); if(mapFragment != null) { FragmentManager fM = getFragmentManager(); fM.beginTransaction().remove(mapFragment).commit(); }

The MapFragment is never removed since we use our host FragmentManager to remove it and the ChildFragmentManager to find it.

Ulloa answered 13/11, 2016 at 14:18 Comment(0)
T
0

You are removing wrong Fragment(Map Fragment), You have to remove "ClinicFragment" Fragment.

Thuthucydides answered 28/7, 2017 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.