|Fragment And Activity Working Together|
|Written by Mike James|
|Thursday, 27 March 2014|
Page 1 of 5
The real problem with using Fragments is making them work together with Activities. This comes down to working out how to allow the Activity to communicate with the Fragment and vice versa. It is a tricky problem and the solution is often just accepted without a deep understanding of the how and why. It is time to take a close look at the Fragment template.
Android Adventures - Mastering Fragments & Dialogs
This book is currently being revised. Chapter 5 and later refer to an earlier version of Android Studio - revisit for updates.
If you are interested in creating custom template also see:
Using The Fragment Template
Suppose you want to add another Fragment to a project.
The steps are nearly always the same - create an XML layout and add a class that extends Fragment. In fact this is so regular you might expect some help from Android Studio to do this.
You would be correct and there is a Fragment template that makes it easy
Start a new Blank Activity project, or any project type for that matter. All we are going to do is add a Fragment to the project using the Fragment template.
To do this first navigate to the java folder and the MainActivity file, right click on it and select New, Android (Other).
From the choices of component you can insert into the project select Fragment (Blank):
At the next screen you can customize the Fragment. In many cases you will want to leave uncheck some of the options but in the spirit of finding out what they are all about let the default selection stand.
When you click Finish button a complete Fragment is generated for you including the XML layout, unless you deselected Create layout XML, and the java file.
We need to look at each of these in turn.
The XML layout is straightforward. You get a FrameLayout with a TextView saying Hello blank Fragment.
The Java code is much more complex than you might have expected and it includes some features of using Fragments that we haven't so far looked at. Although these might be considered "best practices" you don't have to use them if you would prefer simplicity.
As these features are general, you can make use of them in your own Fragments even if they are not generated by the template it makes sense to explain them in isolation.
In other word let's use the generated Fragment to learn some more advanced ways of working with Fragments.
The Problem With Fragments
Before we start on examining the code generated by Android Studio it is worth spending a few moments considering what the real difficulty the Activity has in working with the Fragment.
In most cases the Activity can create an instance of an object and customize it by providing initializing data in the constructor or by setting properties soon after creating the object. It could also wire up event handlers directly to the object in the usual way so that it could signal that something needed attention.
None of this works with Fragments for the simple reason that a Fragment can be destroyed by the system at any time and recreated without initialization and without event handlers etc.
For this reason the Fragment has to save and restore its state in the same way that an Activity has to.
However there are additional problems with a Fragment. In general other objects don't link into an Activity any deep way because an Activity is supposed to do something in its own right. A Fragment on the other hand is suppose to work closely with an Activity. It is the Activity's UI component and as such there has to be links from the Activity into the Fragment and more importantly the Fragment has to be able to connect with the Activity.
This is difficult because say the Activity hooks up an event handler to some Fragment generated event or even to a widget in the Fragment generated UI, then when the Fragment is recreated the event handler will also have to "reconnected" - but in general the Activity doesn't know when a Fragment has been recreated and so can't remake the connection. There are other difficulties which will become apparent.
So we have three problems to solve -
All of these have to work after the Fragment has been destroyed and recreated.
The hardest part is implementing something like an event mechanism. To do it properly requires the use of some moderately sophisticated Java and object-oriented ideas.
A standard way to customize an object is to pass arguments into its constructor. You might think that you could do the same with a Fragment by providing a constructor with parameters and you can do this.
However a Fragment also has to have a parameterless constructor which is used by the system to recreate the Fragment. This is provided by the template:
The parameterless constructor is needed because the system cannot know how to call a constructor that accepts parameters.
So if you want to pass a parameter to the newly created Fragment you might use:
If you do define a constructor with parameters then you need to remember to make sure that the parameterless constructor is explicitly included - as it is in the code that the template creates.
That is, you only get a default constructor if you haven't explicitly defined one.
Clearly if we are going to use a constructor with parameters to set things up we are going to have to find a way to persist the parameter values and restore them using something other than the constructor.
We could now continue to the details of persisting the constructor supplies parameters but the template does something slightly different.
Instead of using a constructor to initialise the new instance the preferred method is to use a static factory method. There doesn't seem to be a clear cut reason to prefer this to an overloaded constructor, despite it being described as "best practice". As this is what the template generates, let's take a look at how this all works - but to be clear you could put the same code into an overloaded constructor as demonstrated later.
A factory method is a common idiom in most object-oriented languages and all that happens is that it creates an instance of the object that it is a factory for. Of course for this to be possible it has to be a class or static method. If you are a big doubtful about static methods read the quick introduction below - otherwise skip forward.
A static method is created within the class definition by use of the modifier static. It is different from normal or instance methods in that it is called using the class name. For example to create a static method you would write:
and you could call the static method using
Notice that you call the method treating the class as if it was an object.
|Last Updated ( Saturday, 25 July 2015 )|