|Fragment And Activity Working Together|
|Written by Mike James|
|Thursday, 27 March 2014|
Page 4 of 5
The Solution - An Interface Callback
If you think about it for a moment the way that you ensure that an object has a particular method is to insist that it implements an interface that contains that method.
If you recall an interface is a bit like a class with definitions but no implementation. If another class implements the interface then it has to provide code for everything that the interface defines. One extra detail is that you can access the interface methods on the class by casting it to the interface.
This is a subtle point so let's have an example. If you already know enough about interfaces and how they relate to type then skip the next small section.
If we define an interface:
Then any class that implements the interface has to implement myMethod with the same signature and return type.
Now if we have Class2 that inherits from Class1 we can implement the interface:
Obviously you can now call the interface method on an object of type Class2:
However you can also call the interface methods on an object of type Class1 that happens to be at run time an object of Class2 as long as you cast it to the interface. That is:
An interface allows you to call a method defined in the interface by casting an object that might have been passed to you as a base type to the interface type and not to a specific child class.
Why is this useful?
If we insist that any Activity that uses the Fragment implements an interface with the callback defined then we can cast the Activity to the interface and this works no matter what the type of the Activity is.
So our plan now is to:
1) Define an interface within the Fragment that defines the callbacks that the Activity has to implement to use the Fragment.
2) Make the Activity implement the interface and hence the callbacks
3) Use Fragment onAttach to get the callbacks and store them for later use.
Time to see how the template does this.
The Fragment template generates the following code for the interface:
You are free to change the names of the interface and the method or methods it defines. You can define as many callback methods as you need to signal to the Activity that the Fragment needs attention. Also you can include whatever parameters you like to pass data from the Fragment to the Activity.
In this case we have modified the generated code to pass the Button as a View object to follow the pattern of the event handler used in the earlier examples.
The next step is to save a reference to the interface in a private field for later use each time the Fragment is attached to a new Activity:
First we need a private field to store the callback object in:
and we can now define the onAttach event handler:
This simply casts the Activity to the interface type we have created. In theory every Activity that uses the Fragment should implement the interface but we need to check that it has - hence the try-catch.
One small detail - it is possible for the Activity to remove the Fragment without the Fragment being destroyed we have to remove the reference to the callback interface onDetach:
That's all we need to set up the persistence of the callback.
Now as long as the Activity implements the interface the callback will be hooked up and working whenever the Fragment is attached to an Activity. It can be destroyed and created by the system as many times as necessary and the callback will still work.
To use the callback all the Fragment has to do is call it:
where v is the View object to pass to the Activity.
For example; if you want to activate the callback when the Button is clicked you would write in the onCreateView method:
This creates an event handler for the Button which delegates what has to happen to the interface by calling onFragmentInteraction. Notice that you can't hook up the callback directly to the Button because it is the wrong type. In general it is better to create custom callbacks and use event handlers within the Fragment to call them.
This completes all the code needed to get the Fragment to use a callback provided by any Activity that wants to use it. The final part of the whole thing is getting the Activity to implement the interface.
You can get Android Studio to implement the interface for you by right clicking on its name and selecting Generate,Implement methods. In this case the following method is generated:
This can now be filled out to do whatever you want. In our case transfer the text from the Button to the TextView. This isn't a good use of the callback because, as we have already discussed anything to do with the UI provided by the Fragment should be handled by the Fragment. It does make an easy example however:
If you run this program you will discover that when you click the Button the text is transferred and this still works after your rotate the device.
This has been a long description and a short summery of exactly what happens might make it all seem simpler.
What you have to do to implement Fragment callbacks is:
|Last Updated ( Saturday, 25 July 2015 )|