Alright, in the previous video,
or actually the one before that,
we saw some strange behaviour
when the emulator was rotated into landscape.
And the contents of the TextView were cleared,
which was expected, because Android destroys the activity
when things like a change in orientation happen.
What I didn't explain though, was how come the editText
retained it's contents.
Not sure whether you picked that up, so let's just run that again,
and I'll show you what I mean.
(typing)
Alright, so here's our app running,
so I'm gonna enter some text in here now,
in the editText.
So "Tim was here",
tap the button, and it's expected,
or even though I made a typo,
"Tim was her", 'Tim was here' was meant to be typed.
The point is that it actually worked.
And what I'm going to do is enter something again,
(typing) "Tim was still",
this time I'll type the word corrently, "here".
Alright, now without tapping the button,
we're going to go into landscape mode again,
so I'm going to move that over and go into landscape.
And we'll just close the keyboard down.
And notice that the TextView has been
cleared of its contents,
but the text that I've typed
into the editText is still there.
So, how does that work?
What's actually going on?
It's as though something is Saving State
of our Activity Instance.
No, I haven't developed a speech impediment.
There's a reason I was stressing those three words;
Save, Instance, and State,
to give you a clue as to what might be involved.
Now if you've guessed that it's got something to do
with the Bundle in the onCreate method, over here,
savedInstantState on line 14,
then you're actually right.
Now, a Bundle is an object that can be used to
pass data around, within the Android framework.
Now it's not the only object that can be used for that,
but it's the one being used here.
Now when our Activity starts, the onCreate method is
called automatically by the Android framework.
Now when it's called, it's given a Bundle
containing all the data needed to restore it to the state
it was in, when it was destroyed.
Now when Android destroys the activity as a result of
rotating the device or for a number of other reasons,
the Instant State of the activity is automatically saved,
before the activity is destroyed.
Now all of that is taken care of by the activity
or AppCompactActivity classes,
so because our MainActivity
extends AppCompactActivity,
we get the advantage of that behaviour.
The contents of the editText are saved for us,
because the contents of any editable widgets form
part of the activities Instant Dtate.
That only applies to editable word widgets, though.
The TextView isn't editable,
so therefore the contents aren't saved.
Now, that explains the behaviour
we've just observed with our app,
when I rotated the virtual device into landscape mode.
So if the base class AppCompActivity
contains the functionality
to restore the savedInstanceState
when the activity starts,
that explains why we have to call
it's onCreate method from ours.
Now it might be tempting to remove the super.onCreate
savedInstanceStatecall, that's this call here on line 15,
just to see what happens, so lets do that.
I'm going to comment that out.
Now what we probably would expect to see,
is the app will no longer restore
the state of the editText when the orientation changes.
So what I'm gonna do first is move the orientation
back to what it was.
But now, already, by commenting that out,
I've got this warning appearing;
"Overriding method should call super.onCreate"
which is giving us a hint. But we'll try running,
and go back to the emulator,
and we've got an error, immediately.
Well if you come back over here,
and we come back and click on Logcat,
this little tab down the bottom here,
and scroll up a little bit,
we can see we've actually got an error here.
And the actual error here is
'android.util.SuperNotCalledException'
and basically it tells us that our app
didn't call the super.onCreate method.
So this saving and restoring of state
is so important that the Android framework won't allow
an activity not to call the super method to support it.
And again, we saw evidence of that here,
the fact that it's warning us
just by commenting that line out
that it's going to be a problem there,
and then we tried to run the app,
and it crashed, as you can see there.
The error message here, I think, is very clear about that.
The exception is called SuperNotCalledException,
SuperNotCalledException, over here,
which is pretty descriptive in itself,
and you can see that the actual message
that I spelled out before, talked about our MainActivity
and it didn't call, and how it didn't call through to
the super.onCreate.
And again, I'll just close this logcat down now,
we're getting a red error here,
over here in the gutter,
and we've got the underlining on the onCreate.
So I guess we could have saved time after
seeing that and not proceeding any further,
instead of running the app,
but it is useful to see the exceptions sometimes.
Alright, so lets just go back
and uncomment that again,
so that we remove the error.
Now incidentally,
activities aren't just destroyed when you rotate the screen.
There's a whole set of events
which can result in Android destroying it,
and it doesn't always recreate it for you.
If the system is short of memory, for example,
then the Android framework will kill your app,
if it needs the memory for an app with a higher priority.
Fortunately, that's quite a rare event with modern phones,
as they now have a lot more memory than they used to.
But if you open loads of apps then Android will definitely
kill them if it needs the memory.
Alright, so lets swing over to some slides,
and have a look at the activity life cycle,
as well as the events we can use
in our programmes to handle them.
Alright, so this first slide shows the full
lifetime of an app and
what happens when Android needs more memory,
or the user starts another app
or a new activity within our app.
Now when the activity is started for the first time,
it's onCreate method is called.
Now because this is the first time
the activity is started,
there is no saved state as such.
The savedInstanceState bundle is null,
because nothing needs to be restored.
Now although I've got a call to onRestoreInstanceState
in the diagram, this isn't always called.
In fact, it's only called when Bundle is not null,
so the first time you start this app,
this method will not be called.
There's nothing to restore, so Android doesn't
bother calling it.
And we'll come back to that a little bit later.
So the next methods to be called onStart and onResume.
Now once onStart has been called, the activity is visible
but may not yet be in a state where the user
can interact with it.
This is the visible lifetime of the activity,
and happens between the calls to onStart and onStop.
Now during this part of the lifecycle,
the activity may actually be paused.
Now once onResume has been called, the activity is
in the foreground, and is in a running state.
It's in front of all the other activities
and the user can interact with it quite happily.
This is the foreground lifetime of the activity,
which lasts between the calls to onResume and onPause.
Now there are many events that can result in the activity
going between the running and paused states -
things like the device going to sleep, for example.
Now if you put code in the onPause and onResume functions,
then it shouldn't do a lot.
While the activity's running,
another activity could be brought into the foreground
or the phone could go to sleep,
and you'll see examples of starting
new activities in the course,
when we launch a new activity to perform some actions -
such as editing a contact record.
Now if that happens, the current activity is paused.
The onPause method is called before the current activity
loses control.
Now the activity is still in a happy state,
and there's no need to save the state
and restore it again - it's just no longer in the foreground.
Now if you displayed a dialogue on top of your activity,
you can also put the activity into the paused state,
so onPause will be called.
Now Google recommends that you don't
perform intensive operations in onPause,
and they've changed their recommendation,
They used to state that you had to be very careful
to make sure that your onPause function
completed its tasks very quickly.
Failing to do that could result in the next activity
not receiving the focus in time,
resulting in the user being
unable to answer their phone for example.
Now although things have changed, and your app
won't block any other apps that are trying to start,
you should still make sure that any code
you place in onPause executes quickly.
Updating your remote database is a good example
of something that you should not do in here.
You'd wanna perform things like remote updates
in the onStop function instead.
Now what happens next, after onPause is called,
depends on what goes on with the system.
Now if the user brings the activity back to the foreground,
by dismissing a dialogue, for example,
then onResume is called.
If the system needs more memory
and decides to kill the app, then onStop will be called.
That's represented by the arrows on the
right hand side of the slide.
Now if the user presses the back button
to close your activity,
then the activity is destroyed completely.
The only trace of it then is in the Recent Apps,
but it's no longer running at all
and that's the end of the lifecycle, or of it's lifecycle.
If the user launches it again,
then everything starts from the top.
Now there is no saved state,
so onSaveInstanceState will not be called
and the Bundle passed to onCreate will be null.
However, if the activity is destroyed as a result
of a configuration change
or because Android needs its resources,
then Android, quote unquote, remembers, that it did exist
and was killed by the system.
And when the app is restarted by the user,
its onCreate is called,
with a Bundle containing the saved state.
Now in the case of a configuration change,
the same thing happens
but the activity is restarted automatically.
So there's no need for the user to launch it again.
Now if Android kills an app that's in the foreground,
then something's gone wrong.
You'll always prefer to kill background processes
to recover memory - not the foreground activity.
And that's represented by the arrows on the
left hand side of the slide.
Now obviously, the user powering off the device
is one case where a foreground activity would be destroyed.
Now note that onDestroy may not always be called.
So we'll see in a minute that
onSaveinstanceState and onRestoreInstanceState
aren't always called either.
They're only called if the system detects
there's is a need for them to be called.
And as a result, the Google documentation recommends
that you save user data in onStop,
rather than onSaveInstanceState
Alright, so that's the theory of how it all works,
but how can we test it, and see what's actually happening.
Now one very valuable technique
is to implement all those methods, and put some code
in them that logs the fact tha they're called,
because that lets us see which methods are called,
and what order as well.
Now, you might think it's gonna
be a bit tedious typing in
all those methods that we've discussed
when adding logging to them,
but Android Studio helps with this,
and will do most of the typing for us.
So, I'm gonna switch back to Android Studio now
and we'll have a look at how this all works.
Alright, lets start with the logging.
Now Android Studio used to have, what was called,
Live Templates, which are defined for us
to type in many of the routine bits of code
that are used over and over again.
And one set deals with writing to the logfile.
However, these are being phased out,
so if you're used to using the logt shortcut, for example,
well that won't work in kotlin.
The indication is that it won't ever work,
and Android Studio will have some other mechanism instead.
Now as I don't know what that is at the moment,
we're gonna have to do things the longer way.
Now, I don't wanna go into a lot of detail
about logging at this stage,
and we're going to write debug log entries to the logcat,
so whenever we want to do that.
Now we're going to write debug log entries to the logcat,
so whenever you wanna do that, just use
the code I'm about to type,
and we're going to go into more detail on logging later.
Now the Android Log takes two arguments.
One is a Tag, which usually just identifies the class
that the log entries are coming from.
And because we're gonna be using the same tag
for all entries in this class,
I'm gonna create a Constant for it,
right at the top of the class.
So lets go ahead and do that,
and I'll actually add it
down here, before the class definitions.
I'm gonna do private, (typing) val, TAG.
I'm putting tag in uppercase deliberately.
It'll set that equal to MainActivity.
Now that we've done that, we can use that TAG
whenever we want to log something.
So what I'm going to do is start a new line
in the onCreate method now.
I'm gonna put that as the first line
and add a debug log call.
So I'm going to type, Log with a capital L, dot d.
Then in parentheses it's going to be TAG in uppercase,
comma, and then I'm going to type onCreate,
(typing) colon called.
So we've added a statement here that it's, ultimately,
going to add a debug log call.
And lets go ahead and do the same
in the onClickListener as well,
just in the first line down here,
in the onClick function.
So I'm gonna type Log.d
and TAG in parentheses again,
and we're going to put, in double quotes then,
onClick, (typing) called.
And that's actually it.
Now before we start doing anything else
and looking at those lifecycle functions,
let's actually run the app to see what we've done here.
So I'm gonna go ahead and do that.
Check the app is actually running.
There's our app running,
and if I have a look now at the logcat,
we can see here we've got onCreate called.
That's the output there that we've typed,
and at the moment the other one was
when the button was clicked.
So obviously, we don't see the text for that and
if we swing over there now,
and type in something, "Tim"
and then click on the button,
you can see down here, in the log,
log view, that onClick was actually called.
Now before we start looking at those lifecycle functions,
we should really run this app to see what we've done here.
But what I'm going to do is, firstly, come back over here
because we're still in project view,
and go back to Android view just
so things are a little bit easier for us to see.
And I'm just gonna expand this out
so we can see our apps.
Alright so I'm gonna stop the video here,
and we're going to look at those lifecycle
functions in the next video.
And we're going to be looking at logcat in detail,
and it's probably something that you wanna review
a couple of times, so a separate video
will make that easier.
So lets do that in the next video.