(bright music)
(clicking)
In the previous video, we wrote the code
to use AddEdit fragment to allow
new task details to be entered.
Our main activity now uses two fragments,
MainActivity fragment and AddEdit fragment.
AddEdit fragment is added and removed as we need it,
but MainActivity fragment is included
in the activities layout,
and we're seeing that it can't be removed.
Because MainActivity fragment is part
of the activity's layout, it's easy to see
how its lifecycle must be closely linked
to the activity lifecycle.
When the activity gets destroyed for example,
the fragment also gets destroyed.
But it may be less obvious how the full
activity lifecycle effects our AddEdit fragment,
because the fragment doesn't even exist
when we first run the app.
For that reason, I'm gonna start off
with MainActivity fragment,
then we'll relate what we learn to the AddEdit fragment.
So let's start by having another look at the Google guide
that we've looked previously at.
This is the components guide.
So we're gonna see how the fragment lifecycle
fits into and is controlled by the activity lifecycle.
You may want to review the videos about the activity
lifecycle in section five, because I'll be referring
to the activity lifecycle a lot in this video.
Alright, so this second paragraph on this page
talks about a fragment always being hosted in an activity.
So you can't just create and display a fragment.
They're always in an activity.
The same fragment class can be displayed
in several activities,
and that's one of the advantages of using them.
Now as an example, we could allow our users
to edit task details from the report screen
as well as, from the main task list.
We'd use the same fragment if we wanted to do that.
And wouldn't have to duplicate all the edited fragment
code in the error reports activity.
So the first paragraph talks about,
you can think of a fragment as a modular section
of an activity, which has its own lifecycle,
receives its own input events,
and which you can add or remove
while the activity is running,
sort of like a sub activity that
you can reuse in different activities.
Now moving down to this third paragraph,
it discusses where the fragment lives
in the activity's layout or view hierarchy
as Google calls them.
So we've used both methods, MainActivity fragment
lives in a fragment element of the layout,
where as the AddEdit fragment is added
to a frame layout view group, as when we need it.
Now that should make a lot more sense
now that we've seen it working.
So let's move now on to the lifecycle.
So we come over here and click on Creating a Fragment.
There's a brief diagram here,
and we've already looked at this.
Let's scroll down and have a look.
You can see this one here.
It's very similar to the activity lifecycle
but with a few extra functions.
So this diagram is fine for seeing
the order of the events in our fragments.
But, it doesn't really relate them
to the corresponding activity events.
When we come down here and click on
Handing the Fragment Lifecycle, this one here.
So this shows how the fragment callbacks
fit into the various activity states.
And a little bit further down there's
a Coordinating With the Activity Lifecycle section,
there's a discussion of the extra callbacks
that a fragment actually uses.
And another thing that might be quite useful for you,
there's a complete, a more complete diagram.
Let me paste that link in.
It's on GithHb.
If we scroll down we can see this as well.
Now this is actually quite old
and I can't fit it all on the screen,
but it relates to fragment and activity lifecycle
methods really well.
It also includes the onView Created
and onView Status Restored callbacks
that aren't mentioned in the guide that we were looking at.
So it does try to cover every thing,
and you can see it's really quite comprehensive,
which can be very handy, but as a result,
though it's also quite complicated.
So, I suggest you take the opportunity to bookmark
this page and to use for reference
if you when you need it.
So now that we've seen that, let's go through
the various functions in a slide,
just to keep things a bit simple.
Alright, so starting off, after the activity is created,
it creates any fragment that it contains.
So in our case, that's our MainActivityFragment.
AddEditFragment doesn't get created
because their layout doesn't include it.
We add it in code once the user taps the menu item.
The lifecycle still applies though,
and we'll see how that works in a while.
For now, we'll have a look at each of those functions,
or each of these functions that the Android framework
calls when a fragment is included in an Activity's layout.
So as we discuss each of these functions,
the slides will include a bubble
showing part of the documentation for the function.
And that makes it clearer which function I'm talking about,
and gives a hint of what the documentation
has to say about it.
The fragments onAttach function
gets called first and it's part of the context.
Remember that an activity is a context
so it's a reference to our activity that's posted here.
It's just of type context rather than type activity.
There's also an unattached function that an Activity has
as its argument, but that's been deprecated.
Generally, a context is more useful than an activity.
In fact, if you find yourself trying to refer
to a fragment's activity,
it's likely that you're doing something wrong.
A fragment shouldn't need to know details
about its Activity, other than any interface methods
that the fragment defines.
Between the calls to onAttach and OnDetach,
a fragment has a valid reference to its Activity.
Our AddEditFragment uses that to make sure
it has a listener, when it wants to call
the onSaveClicked function
that its Activities must implement.
So, if you add a fragment in code,
rather that including it in the Activity's layout,
these Lifecycle events will also happen.
They won't be tied to the Activity Lifecycle events.
So what I mean is, you won't see the Activity's onStart
and onResume functions being called, for example,
because the Activity will have already be created
and will be started.
The Fragment will still go through its Lifecycle,
it's just not so closely tied
to the Activity's events in that case.
Right, so moving on, after onAttach, onCreate gets called.
onCreate is conditional.
So, it won't always be called, because it's possible
to prevent a fragment from being destroyed.
We'll come back to that later.
The onCreat function's used to perform
initialization that doesn't involve UI elements.
We shouldn't try to create any widgets,
nor get a reference to them in here.
And that makes sense, because the fragment layout
isn't inflated until the next method's
called the onCreateView.
So onCreateView is where the fragment
creates it's view, if it has one.
It's the fragment's responsibility to inflate its layout
and when Android calls the onCreate View function.
Fragmens don't have to have a view,
in which case this function just returns null.
So that comment from the documentation
is a bit misleading though.
So it implies that onDestroyView doesn't get called
unless your Fragment has returned a view.
That's not the case, as the documentation
for onDestroyView makes clear.
So once the view's been created,
the fragment's view onViewCreated function gets called.
Now that can be useful, if you want to dynamically
alter the fragment's view after creating it.
Generally you'll find that done in onCreateView,
instead after inflating the layout.
Which one you use is down to personal preference, really.
If you had a lot of code in onCreateView,
I'd probably consider moving some of it
to onViewCreated, just to keep things clean.
The documentation, in the bubble on the left,
states that the Fragment's view hierarchy isn't
attached to its parent at this point.
Now, that may seem strange,
because onAttach has already been called.
There's a difference though between the Fragment
being attached to its Activity,
and the Fragment's view being added
to the Activity's layout.
It's the Fragment's view that's being talked about here.
I mentioned that it's possible
to prevent a Fragment from being destroyed
when its Activity gets destroyed.
So if that happens, onCreate won't be called
because the Fragment wasn't destroyed,
there's no need to create it again.
However, if we think about it,
if the activity does get destroyed, then all its widgets
its entire layout, must also then be destroyed.
Our Fragment's widgets appear in the Activity's layout,
so it also follows that our Fragment's
layout must be destroyed.
The Fragment may still esist, but it has
to inflate its layout again
and restore any state that's visible on the UI.
We'll be looking at preventing a Fragment
from being destroyed later.
For now though, just bear in mind
that a Fragment's views have
to be re-created and added to the Activity's layout
whenever the Activity gets destroyed.
Next, we get onActivityCreated.
That's an important callback because before this is called
we can't rely on the activity
being in a fully created state.
Once onActivityCreated has been called,
we know that the Activity's onCreate function has finished.
All these Lifecycle diagrams, even the ones we've created
for these sides, can give the impression
that the Activity's onCreate function
finishes before onAttach gets called.
That's not true and we'll be seeing
proof of that when we run our app soon.
You can't be sure that the Activity's onCreate
function has finished until onActivity gets called.
That can sometimes be important, so keep that in mind.
In the Fragment, each of these functions
will finish before the next one gets called.
But Fragment functions can be called while an Activity
function is still executing.
That's certainly true of the Activity's
onCreate function as we'll see.
onViewStateRestored can be a good place
to make any final changes to the Fragments's UI.
The documentation mentions ticking a checkbox for example.
Depending on the arguments passed to your Fragment,
you may need to display different information on the screen.
Remember that things like EditText and CheckBox widgets
will take care of restoring their own state.
We've seen that a few times,
when we type into an EditText,
then rotate the device.
If for some reason you, wanted to change
the state of an EditText, and not have that change replaced
when the EditText restores its own state,
then this would be the place to do that.
That's probably not a common thing to do,
and the Google diagrams don't even show this function.
But it's there if you need it.
After onViewStateRestored has been called,
the Activity is in the Started state
and its onStart function gets called.
So it's visible to the user, but not yet fully functional.
The fragment then gets its onStart function called.
That seems to be how it works,
but there's nothing in the documentation that guarantees
the Fragment's onStart will be called after the Activity's.
Finally, onResume is called
for the Activity and the Fragment.
They're now running and responding to the user.
You'll notice that the slides show null
being passed into many of these function.
Those are all the functions that receive
a savedInstanceState Bundle,
when the Activity's recreated.
We're showing null because we're showing
the function that are called
when the Activity's first created.
When Android recreates the Activity
and therefore the Fragment, there will be a Bundle available
in each of those functions.
onRestorInstanceState doesn't appear,
because Fragments don't have that function.
As there are five other function that all receive
the savedInstanceState Bundle,
it's probably not surprising that they didn't bother
including that function into a Fragment.
There's one more slide to see,
before we look at the Lifecycle
functions when the Activity's destroyed.
On this slide, I've included a snippet
from the logcat of a running app.
The entries are coloured to match the Activity
and Fragment headings.
This shows two things that I mentioned
in the previous slides.
The first is that the Activity's onCreate function
is still executing while the Fragment
gets its first four function calls.
But after the onViewCreated gets called,
the Activity's still executing its onCreate
you can see the entry that twoPane is false
coming from the Activity's onCreate.
The second is that the Activity's onStart function is called
before the Fragment's onActivityCreated.
The diagrams tend to show the Activity and Fragment onStart
functions next to each other but don't get the impression
that they're called at the same time.
Here, Activity onStart's been moved up to reflect
the position that it gets called, or that it got called,
as shown by those logcat entries.
Alright, so that's a lot to digest
so I'm going to stop the video here.
In the next one, we're gonna go through
the lifecycle functions that are called
when the Activity gets destroyed.
So I'll see you in the next video.