30

I know that when you're first instantiating a fragment you can pass arguments using setArguments(Bundle) and retrieve them in the fragment using getArguments().

However, in my app I have fragments that will be detached and attached several times after they've been added to an activity. On re-attach, I may need to pass a fragment an argument to modify its content prior to reattaching it. I can use setArguments the first time I display the fragment, but on subsequent occasions that won't work. The savedInstanceState will not work in this case as I won't know the value of the argument prior to detaching the fragment.

I know I could just implement a method that I would call before attaching the fragment that would set an argument, but it just seems like this is something that might already be in the API and I'm just not seeing it.

Is there something built-in that will allow me to do this, or will I have to implement this on my own? For the record, I am using the support package (v4).

Many thanks!

Benoit Duffez
  • 11,839
  • 12
  • 77
  • 125
Jay Lamont
  • 2,867
  • 3
  • 17
  • 14
  • What do you mean by re-attach? Fragments will be attached to an activity only once(AFAIK) and if it is detached from the activity it is destroyed. Do you mean when the user hits the back button the fragment is returned to the layout? – 500865 Mar 07 '12 at 23:06

4 Answers4

26

Yes, if you have called setArguments(bundle) before your fragment becomes active. Then your fragment from there after has a bundle that you can update. To avoid your issue you must update the original bundle and must not invoke setArguments a second time. So following your initial fragment construction, modify fragment arguments with code like

frg.getArguments().putString("someKey", "someValue");

The arguments will then be available in your fragment and will be persisted and restored during orientation changes and such.

Note this method is also useful when the fragment is being created via xml in a layout. Ordinarily one would not be able to set arguments on such a fragment; the way to avoid this restriction is to create a no argument constructor which creates the argument bundle like so:

public MyFragment() {
    this.setArguments(new Bundle());
}

Later somewhere in your activity's onCreate method you would then do:

FragmentManager mgr = this.getSupportFragmentManager();
Fragment frg = mgr.findFragmentById(R.id.gl_frgMyFragment);
Bundle bdl = frg.getArguments();
bdl.putSerializable(MyFragment.ATTR_SOMEATTR, someData);

This places data into the argument bundle, which will then be available to code in your fragment.

user3978046
  • 261
  • 3
  • 3
  • Ya, but is there a way to get your fragment to notice that you'd added arguments to the bundle? I suppose I could add the arguments and then expose a method on the fragment the activity can call to force it to re-check the arguments. Problem with that is that the activity doesn't know what stage in the life cycle the fragment is at. – Glaucus Sep 14 '16 at 21:15
  • 1
    @Glaucus I believe that you are looking for a ViewModel class: https://developer.android.com/topic/libraries/architecture/viewmodel With this, you'd be able to update the Fragment based on some state that is coded into a ViewModel. And from your fragment, you can observe any of the fields in the ViewModel to update the fragment views accordingly. – xarlymg89 Oct 15 '18 at 17:30
  • @CarlosAlbertoMartínezGadea You're right. Viewmodels didn't exist back then. And man, I can't even remember why I made that comment in the first place! So much has changed in 4 years! :-) – Glaucus Oct 19 '18 at 03:01
  • 1
    @Glaucus that's very true! I came back by the end of last year to Android development, since 2012, and I was a little bit overwhelmed at the beginning. Now I only code in Kotlin, using Fragments, ViewModel, SQLite with Room... Nothing to do with how and what I coded on 2012 :) – xarlymg89 Oct 19 '18 at 09:43
15

You can just expose a method on your fragment that set whatever you want to pass to it. To call it you can e.g. retrieve the fragment from the backstack by tag or keep an instance reference around from wherever you are calling it from.

This works nicely for me although you need to be defensive in terms of null checks and such as well as aware of the lifecyle your fragment goes through when you attach it or restart it.

From what I can tell there is nothing in the API...

Update: This is still true and works just fine. I found that once this is more complex it is much cleaner and easier to use something like the Otto eventbus. Highly recommended imho.

Manfred Moser
  • 29,539
  • 13
  • 92
  • 123
  • The argument that I'm passing is pretty trivial - it's not actually content that's going to be added to the fragment but the fragment will show/hide content based on its value. It seemed almost a little too straightforward, which made me think perhaps there was an API for what I was doing. Guess not. Thanks for the help! – Jay Lamont Mar 08 '12 at 17:10
3

Is it possible to pass arguments to a fragment after it's been added to an activity?

No.


But if you are looking for ways to communicate with the activity to which a fragment is tied, you can do it the way @manfred has mentioned or other ways described in the Documentation

There is another interesting way to have 2 fragments communicate with each other. That is by using the setTargetFragment and getTargetFragment methods. Here, If fragmentB can affect fragmentA, you will setTargetFragment of fragmentB to fragmentA and when the changes needs to be updated to fragmentA from inside fragmentB, you will get a reference to it by ((fragmentA) getTargetFragment()) and access the method of fragmentA to update it.

Hope it helps. Good luck.

500865
  • 6,920
  • 7
  • 44
  • 87
0

for me i do

fragment.arguments.putAll(newBundle)

then in onStart you can parse it again and set your variables if you need to or do it this way.

j2emanue
  • 60,549
  • 65
  • 286
  • 456