Failure saving state - target not in fragment manager (setTargetFragment)
Asked Answered
H

8

38

I've got a monkey crash whereby

java.lang.IllegalStateException: Failure saving state: FragmentB has target not in fragment manager: FragmentA
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1561)
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:475)
at com.acme.ParentActivity.onSaveInstanceState(Unknown Source)

Basically FragmentA loads up FragmentB and setTargetFragment is called to set FragmentB's target fragment.

FragmentB then simply calls getTargetFragmentin its onCreate method and hangs on to the target for when needed.

Now I'm not doing anything in any of the onSaveInstanceState calls with the target fragment in terms of setting it null, making any saveFragmentInstanceState, putFragment etc. calls. The question is should I be doing something with it?

Thanks in advance,

Peter.

** Edit 1 ** I am using an old version of the support library and have a feeling that this may be fixed in the latest version, will test further and provide a further update if that is the case. However, still interested to know whether I should be doing anything with the target fragment that I'm not currently doing.

** Edit 1 ** Fixed with version 8 of the support library (haven't tried others).

Halfhardy answered 3/5, 2012 at 17:6 Comment(2)
Updating to r7 of the v4 support library seems to have worked for me as well.Legit
having the same issue with v4r18Cuirbouilli
G
37

There are actually two things you should do to resolve this issue:

1. Make sure you use getChildFragmentManager() NOT getFragmentManager() when launching FragmentB from FragmentA

Calling getChildFragmentManager() will return the hosting Fragment's FragmentManager, whereas getFragmentManager() will return the hosting Activity's FragmentManager. It's important to use getChildFragmentManager() because you're nesting a Fragment inside another Fragment, so the parent Fragment should be in charge of handling any transactions with the nested Fragment. If you use getFragmentManager(), you'll run into the issue you're experiencing right now.

2. DO NOT use setTargetFragment() and getTargetFragment(), they will not work when using getChildFragmentManager()

Instead, use getParentFragment(). I believe there is some kind of bug in Android right now where even if you properly call

fragmentB.setTargetFragment(fragmentA, 0);

and then show FragmentB, after a configuration change, calling getTargetFragment() from FragmentB will return itself instead of FragmentA.

Gibbs answered 13/6, 2016 at 16:0 Comment(5)
Answers it perfectly. These are two reasons why you might get that exception.Laurelaureano
Unfortunately, when using PreferenceDialogFragmentCompat from the support v7 preference library, point 2 cannot be ensured as the support library does a call to getTargetFragment()Tallbot
great, 2nd solution worked for me : I used fragment.setTargetFragment(targetFragment.getParentFragment(), requestCode);Karlin
Works like a charm..!! Thank you..!!Unciform
Thank you very much. With your Solution 2.) I was able to fix my exceptions: declared target fragment FragmentB that does not belong to this FragmentManager! In my case I was instantiating Fragment B from within Fragment A using getChildFragmentManager(). When I used fragmentB.setTargetFragment(FragmentA.this) I received the exception. The fix is to use fragmentB.setTargetFragment(fragmentB.getParentFragment()) instead. Note this exception only happens when upgrading to support Lib version 26. (See: https://mcmap.net/q/410783/-why-is-android-o-failing-with-quot-does-not-belong-to-this-fragmentmanager-quot)Espinal
B
14

Here's a workaround:

put this in the fragment that causes the problems:

@Override
public void onSaveInstanceState(final Bundle outState) {
    setTargetFragment(null, -1);
            ...

and remember to set it to the real target fragment when you need it.

Bakke answered 1/5, 2014 at 13:27 Comment(6)
could you explain moreKutzenco
@MinaFawzy What exactly to explain? It gets reset so that it won't cause any more issues.Bakke
I have the same issue , I dont know what exactly cause this issue , I dont use onSaveInstance in any of my fragment and still have this issue , this why I hope you provide some general information about this issue and why you choose this answer Thank youKutzenco
@MinaFawzy Please try to put this function in each of the fragments that have this issue.Bakke
@androiddeveloper you just saved me :)Badillo
This totally sucks. We need target fragments not to null them out.Flavouring
A
6

I had this issue when showing a DialogFrament from another Fragment and using setTargetFragment on the DialogFragment. The issue was solved using getChildFragmentManager() when displaying the DialogFragment.

  1. ActivityA added FragmentA
  2. FragmentA added DialogFragmentB using ActivityA's FragmentManager.
  3. Called dialogFragmentB.setTargetFragment(fragmentA)
  4. Removed FragmentA and added new instance of FragmentA
  5. The FragmentManager associated with ActivityA still contained DialogFragmentB which had the first instance of FragmentA as target fragment.

This caused "Failure saving state - target not in fragment manager" exception to be called.

Afroasiatic answered 16/11, 2016 at 9:34 Comment(0)
B
5

We ran into this issue recently. We have implemented a custom adapter extending android.support.v4.app.FragmentStatePagerAdapter. With android.support.v4.app.FragmentManager, we have set up several fragments in the pager, as well as several other fragments outside of the pager. The fragments are managed in a single activity. There are some instances where we were setting the target (with setTargetFragment) of non-paging fragments to fragments that may or may not be contained in the paging adapter. Because FragmentStatePagerAdapter only maintains a certain number of fragments, the fragments that were set as targets and what FragmentStatePagerAdapter deemed no longer needed, were destroyed...and a potentially inconsistent state if the fragments that had those targets still existed. This led to the exception being thrown whenever the app lost focus (either when the screen turned off or the app went into the background), i.e., when onSaveInstanceState was called.

To prevent this exception, in onSaveInstanceState, we checked to see what fragments were currently in the fragment manager. If there were any inconsistencies (i.e., a "target" fragment was missing), we removed the fragment that had that target set. In our case, we only had three fragments where we were setting a target so we knew exactly what to look for.

I don't believe there is any other way to handle this case, but if anyone has any helpful feedback, it would be much appreciated.

Bag answered 30/1, 2014 at 0:16 Comment(0)
M
5

I just faced this problem and this is what I think is happening and how I fixed it:

Your FragmentA instance is being destroyed and another one is being created when there is a device rotation, for example. When this happens, your FragmentB keeps holding a reference to a FragmentA which doesn't exist anymore.

In this case, you have to reset FragmentB's target to be the new FragmentA instance.

I did that with the following code in FragmentA:

@Override
    public void onAttach(Context context) {

        super.onAttach(context);

        FragmentB fragment = (FragmentB) getFragmentManager().findFragmentByTag(FragmentBtag);

        if (fragment != null) {
            fragment.setTargetFragment(this, 0);
        }


    }

This way, whenever the FragmentA is attached to the Context, ie: a device rotation happens, FragmentB's target is reset, if FragmentB was created at first hand (if so, it would be on FragmentManager).

I hope it helps.

Moneymaker answered 24/7, 2016 at 3:12 Comment(0)
S
4

Be sure that you've added both fragments to the backstack!

I just ran into this issue when adding a new 'called' fragment for result on top of a 'target' fragment. Initially, I was getting the same error, which stopped occurring as soon as I added both fragments to the back stack whenever I used them.

The issue occurred on screen rotations, so it was easy to reproduce.

Samurai answered 9/7, 2014 at 21:18 Comment(1)
In my case, one of the fragments is part of a ViewPager and therefore not on the backstack and I can't add it there. The workaround from @androiddeveloper worked in my case. Anyway your solution sounds like the way to go :)Gamecock
C
1

There were few changes regarding onSaveInstance() lifecycle order between Pre-HoneyComb and post-Honeycomb libraries. Please refer this article for more info:

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

Calciferous answered 17/9, 2013 at 10:33 Comment(0)
A
0

In my case the issue was about calling setTargetFragment on wrong Fragment.

Was: FragmentA.setTargetFragment(FragmentB);

Should be: FragmentB.setTargetFragment(FragmentA);

Augsburg answered 6/3, 2018 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.