2

Total beginner here.

As I understand, fragments should communicate with each other through their hosting activities as a way to stay independent and reusable in other situations.

I’ve read that should be done by declaring interfaces in the fragment and implementing them in the activity. Is that the best way to go about it “just” because you can make sure the activity is ready for that communication (it really has that method to deal with the communication)?

As I’m having a hard time wrapping my head around interfaces (and lots of others things in java/android, for that matter), could this be done without the interface? Could I get a reference to the hosting activity in the fragment and just call the activity’s method?

(fragment class)

Activity activity = getActivity();

activity.doThatThingToOtherFrag(String myString);

(activity class)

Fragment otherFragment = getSupportFragmentManager().findFragmentById(R.id.myOtherFrag);

public void doThatThingToOtherFrag(String string) {
//do something to myOtherFrag
}

Or is there something else about implementing an interface in this case that I’m not getting?

* EDIT *

Let’s say I reuse that fragment in another activity. As long as that activity also has a doThatThingToOtherFrag(String myString) method, I can get a reference to it through getActivity() and still call activity.doThatThingToOtherFrag(String myString) from my fragment, right? I wouldn’t have to change anything in my fragment code -- or am I’m missing something here?

I guess my question should be: is the interface there only to MAKE SURE the/any hosting activity implements a doThatThingToOtherFrag method? Or is there something else I don’t know about interfaces in this situation? Thanks for the help!

bernardo.g
  • 826
  • 1
  • 12
  • 27
  • well, you are missing the fact its not going to be `Activity` but `MyActivity` and your method call more like `((MyActivity)activity).doThatThing` .. in other words since `doThatThing` belongs to `MyActivity` you are going to have to cast which tightly couples to MyActivity. – trooper Sep 17 '16 at 15:55
  • ...to reuse you will have to change this cast each time, unless you program to an interface. If you are always dealing with Activity (and not a subclass) then there is no point to the interface, buts its assumed that `doThatThing` is a method you wrote, not something that already belongs to your `Activity` base class. – trooper Sep 17 '16 at 15:58
  • I thought I could cast any subclass of Activity (such as `FragmentActivity`) simply to `(Activity)` and as long as the doThatThing method was there, I wouldn't have to change anything in my fragment code. – bernardo.g Sep 17 '16 at 16:08
  • sure, but in that case you are upcasting - casting upward to a baseclass. Typically you extend from Activity and implement stuff there - to use the methods you added to MyActivity you would need to downcast (which isn't a good habit to get into). – trooper Sep 17 '16 at 16:10
  • an example that doesn't involve casting... suppose your fragment had a method `setMyActivity( MyActivity activity )` where `MyActivity` is basically your app (and extends `Activity`). Now suppose you add a new activity `MyActivity2` and you want to use your fragment there too - woops, you will need to rewrite your `setMyActivity` method to pass `MyActivity2` instead. very inconvenient. – trooper Sep 17 '16 at 16:20

5 Answers5

4

"Program to the interface." is a common maxim of object oriented programming. You can certainly just communicate with the activity directly without using the interface. However, this create a tight coupling between the fragment and the activity.

Consider a situation where you want to reuse the same fragment in two different activities. Using interface allows the flexibility to do this.

Answer to edit:

As long as that activity also has a doThatThingToOtherFrag(String myString) method, I can get a reference to it through getActivity() and still call activity.doThatThingToOtherFrag(String myString) from my fragment, right?

I assume you mean something like this:

Activity activity = getActivity();
activity.doThatThingToOtherFrag(String myString);

This won't compile because Activity doesn't have a method named doThatThingToOtherFrag(). However, if you do

FragmentCommunicationInterface activity = (FragmentCommunicationInterface) getActivity();
activity.doThatThingToOtherFrag(String myString);

now it will compile. This has yet another problem: what if the fragment where this is called was added to an Activity which doesn't implement FragmentCommunicationInterface. Now you will get a run-time error when you do the case.

One possible solution to this is to take a FragmentCommunicationInterface as an argument to the fragment's constructor:

public class MyFragment extends Fragment {
    private FragmentCommunicationInterface communication;

    public MyFragment(FragmentCommunicationInterface communication) {
        this.communication = communication;
    }
}

Now you create a fragment with

MyFragment frag = new MyFragment(this);

Another advantage to using an interface is that the interface can be implemented by any class not just classes which extend Activity. This allows even more flexibility than I hinted above. It allows you to organize the code to communicate with the activity or other fragments in any way you want.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Is the interface used only as a way to guarantee the activity has a doThatThingToOtherFrag method implemented or is there a reason I still don't know about? Please read my edit if possible. Thanks! – bernardo.g Sep 17 '16 at 15:56
  • @bernardo.g That is one reason. See my edit for details regarding your own edit. – Code-Apprentice Sep 17 '16 at 22:48
2

It's not really necessary, but it may be desirable.

In general, interfaces help code not depend on the class whose code you call. You don't really care which Fragment class you're invoking, what you really care is that whatever you're invoking, it needs to have the ability to doThisOrThat() -- so that's what you put in your interface.

This decoupling is actually about helping to use polymorphism. Say your code may use two Fragment classes where you now use one, and both ca n doThisOrThat(). In that case using an interface will help you write cleaner code, because you won't need to write duplicate code to invoke the same method, except for changing what you cast it to.

Anyway, in order to really decouple you classes, you might want to learn about EventBus (doesn't matter which implementation).

2

This way you can make your fragment work with any activity that implements the interface. This completely adds to the independence and reusability you pointed out in your question.

If you would use the activity class's method to 'communicate' you would not be able to make it work (interface with) other activities because they are of a different class.

whitebrow
  • 2,015
  • 21
  • 24
  • Could you please take a look at my edit? It didn't fit here. – bernardo.g Sep 17 '16 at 15:54
  • 1
    The method you want to call from the fragment must be defined either in a class or in an interface implemented by a class at runtime so that it is properly linked. Remember: In Java at runtime names do not exist; they are converted to symbols and thus strict definition is compulsory. – whitebrow Sep 17 '16 at 16:35
  • 1
    In other words: Two methods with the same name will have different symbols at runtime. – whitebrow Sep 17 '16 at 16:36
  • Oh, I thought I could get Android to look into any Activity and to use a method called `doThatThingToOtherFrag ` as long as that method was implemented there. – bernardo.g Sep 17 '16 at 16:44
  • This is what interfaces are all about: They guarantee that certain methods are implemented so that the class that implements the interface can be interfaced with. – whitebrow Sep 17 '16 at 18:49
0

One good reason not to do the way you implemented as above is loose coupling. It is a program design pattern to create well-designed software. I am not gonna create a new discussion of it here since a lot of other discussions are available in StackOverflow.

What is "loose coupling?" Please provide examples

Please take time to understand this concept as this will save you a lot of time as a programmer.

Cheers!

Community
  • 1
  • 1
user1506104
  • 6,554
  • 4
  • 71
  • 89
-1

Interfaces are best for communicating two fragments, 2 activities or communicate with any class, because interface triggered at same time when other want to communicate.

Learn Pain Less
  • 2,274
  • 1
  • 17
  • 24