11

We all know getParentFragment of Fragment is introduced in API 17.

So what if we want to get parent fragment in API 16 and below (Considering that I use native Fragment with support FragmentStatePagerAdapter and have no problem with nested fragments)

Is there any better way than mine?

In parent:

public class ParentFragment extends Fragment {

public static ParentFragment StaticThis;
...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

StaticThis = this;

...
}

In child:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
         parentFragment = (ParentFragment) getParentFragment();
else
         parentFragment = ParentFragment.StaticThis;
Mohsen Afshin
  • 13,273
  • 10
  • 65
  • 90
  • 3
    Nested fragments was not supported until API Level 17, or via the Android Support package. Hence, there is no concept of a "parent fragment" until API Level 17. Your "solution" is a memory leak. – CommonsWare Dec 04 '13 at 13:17
  • I'm using ViewPager and need to talk back from items to container of ViewPager. @CommonsWare so there's no safe way to talk back to parent fragment (call some method) below API 17? – Mohsen Afshin Dec 04 '13 at 13:24
  • 1
    Since there is no parent fragment below API 17, there is no way to talk to a parent fragment below API 17. – CommonsWare Dec 04 '13 at 13:34
  • @Snicolas: There is no concept of "parent fragment", except on API Level 17+ or by using the fragment backport. If you are on either of those, use `getParentFragment()`. – CommonsWare Jun 24 '14 at 10:52
  • @CommonsWare, other ways could still be possible. For instance, I have been looking if we could compare the references of each fragment to its childMananger and looping through the trees recursively until you find the parent fragment (has a manager that your child fragment has the child of). – Snicolas Jun 24 '14 at 20:28
  • @Snicolas: If there is a `childManager`, then there is a `getParentFragment()`. – CommonsWare Jun 24 '14 at 20:32
  • @CommonsWare, lol, you're so right. 17+ both. If you wanna submit a proper answer, I would accept it.. – Snicolas Jun 24 '14 at 20:44
  • @Snicolas: You can't accept an answer, as it is not your question. And my comment does not answer the OP's question (in large part, because there is no answer), which is why I put it as a comment. – CommonsWare Jun 24 '14 at 20:56
  • @CommonsWare You right, but I have a bounty pending and your comment answers my bounty so I guess it would be valuable for others too. – Snicolas Jun 26 '14 at 10:09
  • And there are 21 hours remaining @CommonsWare.. – Snicolas Jun 26 '14 at 20:32

3 Answers3

5

Based on your comment if you want to talk back from the "items" in your ViewPager (I'm guessing this is a Fragment) to the container of the ViewPager which is a FragmentActivity you can use an interface.

(1) Either declar the interface in the Fragment itself or as a separate file (2) "Initialize" the inteface in your fragment's onAttach method. For example

 private SomeInterface blah;

 @Override
 public void onAttach(Activity activity){
    blah = (SomeInterface) activity;
 }

(3) Implement the interface in your FragmentActivity.

You can then callback to the FragmentActivity from your Fragment. From there you can call any method you want within the FragmentActivity or, if you get a reference to any of the other fragments that are loaded into your ViewPager, call any public method within that Fragment. This allows you to communicate between fragments and their container without a memory leak.

Rarw
  • 7,645
  • 3
  • 28
  • 46
  • The parent itself is Fragment not FragmentActivity, so I can't use onAttach, instead I pass it as parameter to constructor of child fragments – Mohsen Afshin Dec 04 '13 at 13:59
  • Ah ok - you could still use an interface though. That's better than a static reference. My other idea is to use an inner abstract class that you access from the parent. This way you could call back to the host fragment that way. Kinda that same concept though. – Rarw Dec 04 '13 at 14:07
  • Interfaces are a huge part of OO programing. Why are there so many questions on this? – danny117 Jun 20 '14 at 11:20
  • Idk ask the guy who asked this question – Rarw Jun 20 '14 at 11:43
4

To get the parent fragment in older (and newer) versions, I found a way around:

1) Set the tag of the ParentFragment in your activity (via .add() or .replace()). Check the link below for more info, or step 2 for a similar example in the ParentFragment : http://developer.android.com/reference/android/app/FragmentTransaction.html#add(android.app.Fragment, java.lang.String)

2) In the ParentFragment, collect the tag (using 'this'), and add it to the newInstance() of your ChildFragment:

  FragmentManager fragmentManager = getFragmentManager();
  FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

  // Get the fragment, if you want to re-use it
  ChildFragment fragment = (ChildFragment) fragmentManager.findFragmentByTag();

  // Create a new fragment if it doesn't already exist.
  if (fragment == null)
  {
     // Collect the tag of your ParentFragment and add it to the newInstance() of the ChildFragment
     String parentTag = this.getTag();
     fragment = ChildFragment.newInstance(parentTag);
  }
  // Put the fragment in the .replace() or .add() of the transaction.
  // You might use a childTag as well, but it's not necessary for solving your problem
  fragmentTransaction.replace(R.id.my_fragment_view, fragment, childTag);
  fragmentTransaction.commit();

3) Make sure to save the tag in the arguments of the ChildFragment. Collect the tag from the arguments in onAttach(), and collect the ParentFragment through the 'activity' parameter from onAttach():

private static final String PARENT_TAG = "parent_tag";
ParentFragment parentFragment;

public static ChildFragment newInstance(String parentTag)
{
   ChildFragment fragment = new ChildFragment();
   Bundle args = new Bundle();
   args.putString(PARENT_TAG, parentTag);
   fragment.setArguments(args);
   return fragment;
}

@Override
public void onAttach(Activity activity)
{
   super.onAttach(activity);

   // Collect the tag from the arguments
   String tag = getArguments().getString(PARENT_TAG);

   // Use the tag to get the parentFragment from the activity, which is (conveniently) available in onAttach()
   parentFragment = (ParentFragment) activity.getFragmentManager().findFragmentByTag(tag);
}

4) Now you've got your ParentFragment inside your ChildFragment and you can use it whenever you need it, so where you used this:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
{
     parentFragment = (ParentFragment) getParentFragment();
}
else
{
     parentFragment = ParentFragment.StaticThis;
}

you can now:

parentFragment.justDoSomethingCoolWithIt(); // and prevent memory leaks through StaticThis ;-)
P Kuijpers
  • 1,593
  • 15
  • 27
4

SIMPLE USE SUPPORT LIBRARY WITH FRAGMENT ACTIVITY. http://developer.android.com/reference/android/support/v4/app/Fragment.html#getParentFragment%28%29

Mobeen Altaf
  • 138
  • 1
  • 9
  • Ohhh great, this is really helpful. The api name is same, getParentFragment() so there was confusion, thinking that ....this feature does not exists for API<16. However, you can add more description, to let people get aware of it. Thanks – Nicks Sep 06 '15 at 09:47