Communicating between a fragment and an activity - best practices

139,617

Solution 1

The easiest way to communicate between your activity and fragments is using interfaces. The idea is basically to define an interface inside a given fragment A and let the activity implement that interface.

Once it has implemented that interface, you could do anything you want in the method it overrides.

The other important part of the interface is that you have to call the abstract method from your fragment and remember to cast it to your activity. It should catch a ClassCastException if not done correctly.

There is a good tutorial on Simple Developer Blog on how to do exactly this kind of thing.

I hope this was helpful to you!

Solution 2

The suggested method for communicating between fragments is to use callbacks\listeners that are managed by your main Activity.

I think the code on this page is pretty clear: http://developer.android.com/training/basics/fragments/communicating.html

You can also reference the IO 2012 Schedule app, which is designed to be a de-facto reference app. It can be found here: http://code.google.com/p/iosched/

Also, here is a SO question with good info: How to pass data between fragments

Solution 3

It is implemented by a Callback interface:

First of all, we have to make an interface:

public interface UpdateFrag {
     void updatefrag();
}

In the Activity do the following code:

UpdateFrag updatfrag ;

public void updateApi(UpdateFrag listener) {
        updatfrag = listener;
}

from the event from where the callback has to fire in the Activity:

updatfrag.updatefrag();

In the Fragment implement the interface in CreateView do the following code:

 ((Home)getActivity()).updateApi(new UpdateFrag() {
        @Override
        public void updatefrag() {
              .....your stuff......
        }
 });

Solution 4

To communicate between an Activity and Fragments, there are several options, but after lots of reading and many experiences, I found out that it could be resumed this way:

  • Activity wants to communicate with child Fragment => Simply write public methods in your Fragment class, and let the Activity call them
  • Fragment wants to communicate with the parent Activity => This requires a bit more of work, as the official Android link https://developer.android.com/training/basics/fragments/communicating suggests, it would be a great idea to define an interface that will be implemented by the Activity, and which will establish a contract for any Activity that wants to communicate with that Fragment. For example, if you have FragmentA, which wants to communicate with any activity that includes it, then define the FragmentAInterface which will define what method can the FragmentA call for the activities that decide to use it.
  • A Fragment wants to communicate with other Fragment => This is the case where you get the most 'complicated' situation. Since you could potentially need to pass data from FragmentA to FragmentB and viceversa, that could lead us to defining 2 interfaces, FragmentAInterface which will be implemented by FragmentB and FragmentAInterface which will be implemented by FragmentA. That will start making things messy. And imagine if you have a few more Fragments on place, and even the parent activity wants to communicate with them. Well, this case is a perfect moment to establish a shared ViewModel for the activity and it's fragments. More info here https://developer.android.com/topic/libraries/architecture/viewmodel . Basically, you need to define a SharedViewModel class, that has all the data you want to share between the activity and the fragments that will be in need of communicating data among them.

The ViewModel case, makes things pretty simpler at the end, since you don't have to add extra logic that makes things dirty in the code and messy. Plus it will allow you to separate the gathering (through calls to an SQLite Database or an API) of data from the Controller (activities and fragments).

Solution 5

I made a annotation library that can do the cast for you. check this out. https://github.com/zeroarst/callbackfragment/

@CallbackFragment
public class MyFragment extends Fragment {

    @Callback
    interface FragmentCallback {
       void onClickButton(MyFragment fragment);
    }    
    private FragmentCallback mCallback;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt1
                mCallback.onClickButton(this);
                break;
            case R.id.bt2
                // Because we give mandatory = false so this might be null if not implemented by the host.
                if (mCallbackNotForce != null)
                mCallbackNotForce.onClickButton(this);
                break;
        }
    }
}

It then generates a subclass of your fragment. And just add it to FragmentManager.

public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().beginTransaction()
            .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), "MY_FRAGM")
            .commit();
    }

    Toast mToast;

    @Override
    public void onClickButton(MyFragment fragment) {
        if (mToast != null)
            mToast.cancel();
        mToast = Toast.makeText(this, "Callback from " + fragment.getTag(), Toast.LENGTH_SHORT);
        mToast.show();
    }
}
Share:
139,617
Kristy Welsh
Author by

Kristy Welsh

Updated on June 05, 2021

Comments

  • Kristy Welsh
    Kristy Welsh almost 3 years

    This question is mostly to solicit opinions on the best way to handle my app. I have three fragments being handled by one activity. Fragment A has one clickable element the photo and Fragment B has 4 clickable elements the buttons. The other fragment just displays details when the photo is clicked. I am using ActionBarSherlock.

    Screen shot

    The forward and back buttons need to change the photo to the next or previous poses, respectively. I could keep the photo and the buttons in the same fragment, but wanted to keep them separate in case I wanted to rearrange them in a tablet.

    I need some advice - should I combine Fragments A and B? If not, I will need to figure out how to implement an interface for 3 clickable items.

    I considered using Roboguice, but I am already extending using SherlockFragmentActivity so that's a no go. I saw mention of Otto, but I didn't see good tutorials on how to include in a project. What do you think best design practice should be?

    I also need help figuring out how to communicate between a fragment and an activity. I'd like to keep some data "global" in the application, like the pose id. Is there some example code I can see besides the stock android developer's information? That is not all that helpful.

    BTW, I'm already storing all the information about each pose in a SQLite database. That's the easy part.

  • Kristy Welsh
    Kristy Welsh over 11 years
    Yeah, that way seems confusing, I have 2 fragments that need to somehow communicate with each other through the activity. Is there a better tutorial out there on how to do this?
  • Squonk
    Squonk over 11 years
    @KristyWelsh : I wonder if you have developed your own concept of what Fragments really are and how they work rather than grasped the actual concept of the Fragment design goal. The concept of communicating with the Activity using interfaces is no different from having an Activity implement View.OnClickListener so a Button press results in an item being added to a ListView (for example). You might have an Activity with FragmentA and FragmentB but NOT FragmentC - in this case, the concept of having FragmentA "know" how to talk to FragmentC directly is redundant.
  • cjayem13
    cjayem13 over 9 years
    Does anyone know why the example on the android developers page regarding use of an alert dialog doesn't use an interface to communicate with the activity? developer.android.com/reference/android/app/…
  • jk2K
    jk2K over 8 years
    @cjayem13 In some cases, you might need a fragment to share events with the activity, A good way to do that is to define a callback interface, Perhaps you can look at this Communicating with the Activity
  • DeaMon1
    DeaMon1 almost 8 years
    Interfaces are good. But for looser coupling, use broadcast listeners.
  • Rikki Gibson
    Rikki Gibson over 7 years
    Sure, but what happens when your activity winds up providing several distinct services to a fragment because the fragment can't do lots of Context-ey things by itself? I reached the point of having my activity implement 4 different interfaces for communicating with fragments before throwing my hands up and just letting the fragments know about the activity, because those fragments aren't going to be parented in a different activity ever in my case, and if they did I'd probably have to fix other stuff to make that work smoothly anyway.
  • Eenvincible
    Eenvincible over 7 years
    The modern approach would be to use Events which actually decouples your project code and this answer being from 2014, although works to an extent, should not be the only solution to this scenario!
  • Parag Kadam
    Parag Kadam almost 7 years
    @Eenvincible Yes you are right please update your answer accordingly for people who come here in the future.
  • b005t3r
    b005t3r over 6 years
    What is proposed here is doing things backward - Activity has to implement the interface and fragments have to guess which interfaces Activity implements? Listener approach is much more flexible.
  • Linxy
    Linxy about 6 years
    Architecture components are also a new and clean way to handle communication with loose coupling.
  • xarlymg89
    xarlymg89 over 5 years
    @Eenvincible the link to Simple Developer Blog is dead. Actually, the server of the blog is not found.
  • Eenvincible
    Eenvincible over 5 years
    You might have to switch to google DNS servers! The site is working!
  • ChristianB
    ChristianB over 3 years
    Please provide an example. You just defined some dependency. How is it used? What is different?
  • Admin
    Admin about 3 years
    This works nicely - thanks for sharing good explanation :)
  • Bokili Production
    Bokili Production almost 3 years
    One of the best answers on the net. Thanks for sharing.