So I finished the last video by saying
that there's some important implications
of the activity lifecycle, as it relates
to our activity. Now one of them is that
if we want to save some data so that
it's available next time the app is
launched, then we can't rely on code in
onSaveInstanceState to do that.
That's because onSaveInstanceState
isn't always called. In fact, it's only
used when Android knows that it may be
relaunching the activity. The recommended
place to put code to save your own app
data is in the onStop method. Now the
second thing is that Android will
automatically save the state of widgets
that it expects to contain data, and will
restore that data again when the
activity's restarted. Now the third one
is less obvious, but it's the reason I've
shown you all of this. If we want to
save program state that Android doesn't
know about, then we need to do that in
onSaveInstanceState and restore it in
onRestoreInstanceState. So the sort of
thing I'm talking about here is the
contents of the TextView. Now Android
doesn't save the state of TextView
widgets for us because users can't type
into them, so they don't usually change. But
in our case, ours does change, so
ultimately that responsibility to save
the state comes back to us, before the
activity is destroyed. Now that's a bit
arbitrary in this example, because it's
possibly not clear whether the contents
of the TextView are state or whether
they're our applications' data. So in a
calculator app, for example, the results
are really state. I don't think many
users would expect the previous
calculation to appear the next time that
they launch the calculator app. But if
this was a data entry screen for a
contacts app, though, then users may expect
the details to still be present, even
though they hadn't tapped a Save button
to store them. So how do you define data
that the users input into your app? Well
that really depends on what the app does
and what's being entered.
So if our button click counter app was
used to store a shopping list, for
example, then those details should be
considered as data. In other words, they
should still be there the next time the
app's launched. This section is about the
activity lifecycle, though, so we're going
to treat any input as state rather than
data. We will be looking at saving your
applications data, though, later in the
course.
Now one thing we've learned from
students in previous versions of this
course, is that it's not clear what we
mean by state and app data. So when I
talk about state, I'm referring to things
like the values of our variables and the
contents of the editText and the Text
View widgets, while the program's
running. Now when Android destroys our
activity, we want it to return to the
same state when it's recreated. What that
means is that the editText should
contain whatever it contained, before it
was destroyed, and the TextView should
also have the same text as it had before
the app was destroyed. Now each time the
user taps the button, their text is taken
from the editText widget and appended
to the TextView. And it's a bit grim that
if they rotate the device they lose
everything that they've typed in previously.
So the state refers to the things that
need to be restored, to make things like
a device rotation appear seamless to
the user. So I'm willing to bet that
before you started programming for
Android, you weren't aware that apps got
destroyed when you rotated the device.
Now your users are also unlikely to be
aware of this, so we need to make sure
that everything looks the same after a
rotation, as it did before that rotation.
So that's state. Your programs' data isn't
the same thing. Now if the user
starts to type some input into the edit
Text, then uses the back button to close
the app, they probably wouldn't be too
surprised if that input wasn't still
there when they launched the app again, two
days later. But on the other hand, if
they'd created a list of items in the
TextView then tapped our Save button,
they'd probably be very unimpressed if
they couldn't load that list back up
again, two days later. Now I know I
haven't added a Save button, but
hopefully that explains the difference
between state and the apps' data. The data
is stuff that users would expect to
still be available when they launch the
app again, days or even months later. If
you typed a message into Facebook or
Twitter, then minimized your browser, you'd
expect the message to still be there
when you restored your browser window -
that's state. If you closed the browser
without posting the message, you probably
wouldn't be surprised that the message
was no longer there when you logged back in,
but on the other hand, if you'd clicked the
post button,
you would expect to see the message.
So that's app data. So it's exactly the
same message, the same text, but context
is everything.
So as I've said, we're not going to be
dealing with storing data just yet. That
will come later in the course. So for
this app, anything the user types in
won't be saved when they quit the app. We
should make sure it's still there when
they do things like rotating the device,
though. So let's go ahead and do that. Al
right so a bundle contains a list of key
value pairs, and we can add new data to
the bundle, by saving the data with a
name that we use to get the data back.
Now one way to think of a bundle is like
the mail being delivered to a house. Each
envelope will have a person's name on it -
each name is a key. Inside the envelope
will be the value that's associated with
the key. Now when the people in the house
want to get their mail, they'll use the
key - their name - to pick up the correct
envelope. The key was also used when the
data was put into the envelopes - the name
was written on the outside. So when we
store a value in a bundle, we're
associating the value with a key. When we
want to get the value back out of the
bundle, we provide the key to ensure we
get the correct value. Alright, so we
need to make some changes to our code
now, and because we're going to be using
the key name at least twice, we're going
to create a constant to store that name.
So we're gonna come down here,
below the line 12. I'm going to change
line 12, firstly, to a const. So I'm going
to make that private const val and then TAG.
We're going to leave that line as it is
then. On the next line, though, we're going
to add private const val and we're going
to call this one, all in uppercase, TEXT
_CONTENTS equals, we're going
to call it TextContent. So now that
we've done that, we can save the Text
Views' content in the onSaveInstance
State. So I'll do a search for that, onSave
InstanceState, so down here. We're going
to add some code in there to save that.
So we need to put this code after the
save dot, sorry the super.onSave
InstanceState call on line 63. So we're
going to type
outState?.putString.
Then we're going to use our new
TEXT_CONTENTS
comma, and we're going to type textView
question mark dot text.toString. Now
a TextView is a nullable type, so we
need to put a question mark after its
name, just as we did earlier. The same is
true of the outState parameter. So it's
declared as Bundle? and you
can see that on line 6. So consequently,
we have to use the question mark when we
attempt to access its properties and
functions. So we're adding the value we
want to store to the bundle, using a key
that we can use to get that same value
back later. Now I used the constant TEXT
_CONTENTS so I don't have to
remember exactly what key I used.
Otherwise I might spell it wrong or get
capitalization wrong when getting the
value back from the bundle, and the data
wouldn't be read back. Now, keep in mind
you can store multiple values in the
same bundle. As long as they have
different keys, you can get them back again.
If you give two values of the same type,
the same key, then the second value saved
will replace the first one. So it's
important to make sure that the strings
we use for the keys are unique. Now
notice that I've also called the super
method. I mentioned that we put our code
after that, so we've left that in on line
63. And that's because the super method takes
care of storing all the things that
Android looks after, such as the contents
of an editText that the user has
started typing into. If we don't call
super, only the values we store in the
bundle will be retrieved.
Now all that might make more sense when
you've seen the code to get the data
back. We're going to do that in the on
RestoreInstanceState. So I'm going to
come up here to onRestoreInstanceState
and after the super call, we're going to
type val space and savedString is
equal to, and it's going to be saved
InstanceState?.getString.
It's going to be TEXT_
CONTENTS and two double quotes.
Then we're going to use textView
question mark dot text equals savedString. 233
So this time the value retrieved our
data from the bundle. We're providing the
same key, which is stored in the constant
TEXT_CONTENTS so that the
bundle knows which value we want to
retrieve. And if a string value with the
key TEXT_CONTENTS doesn't appear in the
bundle, that getString function, this
code here on line 49,
well that returns the default value
we've specified, and that's an empty
string so nothing will be printed. And
again, that's if TEXT_CONTENTS
doesn't appear in the bundle. Now that
default value is probably unnecessary
because the bundle should always contain
our data.
Remember that onRestoreInstanceState
will only ever be called if data was
saved,
if onSaveInstanceState was called
before the activity was destroyed, and we
saved the data in onSaveInstanceState
so it should always be present. So once
we've got the value in our savedString
variable, we set the TextViews' text
property on line 50, to the string that we
retrieved from the bundle. Now there's no
need to store the value in savedString
first, so it's actually more usual to
write it this way. So I'm going to comment
those two lines out. You don't want to
just do something like this; so, textView
question mark dot text equals save
InstanceState?.get
String, and it'll be TEXT_
CONTENTS and then two double quotes, as I
mentioned. Alright, and I've left the
original code in there commented out, so
you can see it in the source code for
this video, if you download it. But more
importantly, let's now try and see
whether this works. I'm going to run this,
actually, we'll get our logcat showing as
well.
Alright, so we're going to put it in
our familiar items again, so bread, milk,
cheese. We're going to type in cream
again, and as per normal, I'm not
going to tap the button after I've typed
cream so that we can test that we
haven't broken anything. But now if we
click on rotate, and I'll just click on
back so we can see the, or we can get
rid of the keyboard. We can see that now,
we've actually got our three items
showing back on the screen, the bread,
milk and cheese. And looking at the log
cat, you can see that onSaveInstance
State was called, and also onRestore
InstanceState was called. Now we didn't
save the text ourselves, for what was
in the editText, remember. That was
taken care of for us, by Android. The list
of items in the TextView was saved and
restored by the code we added to the
save and restore InstanceState functions.
Alright, so at this point, our app now copes
when a device's orientation has changed.
Now that may look like a lot of work, but
if you think about it, we really only had
to implement the two functions; on
RestoreInstanceState and onSave
InstanceState. And also, we didn't have to
write a lot of code in either of those,
either. The other overridden methods are
really only added so that we could see
them being called, as the app went
through its lifecycle. Now you might be
wondering what all those methods are for,
really. It's unlikely that Google
included them just so we could see them
being called, so they must have a use.
There's actually all sorts of uses and
it really depends on what your app is
doing. The onPause method would be a good
place to save any data that the user
would want to keep permanently, as long
as you're saving it locally, and you can do
so quickly. Now we've saved the contents
of the TextView to a bundle, but that
wasn't permanently storing it - it was
just a way to cope with orientation
changes and the like. Having created a
shopping list, or whatever, the user would
probably want to store it somewhere, so
they can use that list when they get to
the shops. If we close the activity down
without saving, they'd lose at all.
Now the onPause method could save
that data. onStop, on the other hand, can
be used to cancel a data transfer over
the internet,
with onStart, perhaps, initiating it
again when the app runs again. And it's
also more appropriate to save data
remotely here, rather than in onPause. Now
it's hard to know which, if any, you'll
need until you come to need them, but
when you do you'll be able to work out
which method is the most suitable for
what you want to do, by looking at each
method in the context of the activity
lifecycle. Alright, so that's the end of
our button click counter app. The only
thing left for me to do now is, really,
just come up here to the code menu and
click on Reformat Code, and then we didn't
need to do anything, as you can see
there, everything was correctly formatted.
I've done that just to make sure the
code is formatted nicely, before I add it
to the resources section for this video.
So I'm going to finish the video by
showing you the Google documentation for
activities and the activity lifecycle.
Now I definitely recommend you read
those pages when you want to know more
about how this all works. Now the first
one I'm going to show, I'm just gonna open a
browser here. This first one is the
Activity page from the Android reference
Docs, and the link will be in the
resources section. And that also includes,
if we scroll down a little bit,
Google's diagram on the lifecycle. Now
keep in mind, that Google also produce
guides in their documentation, and the
activities guide is also available, and
there's the link to that, and again in
the resources section.
That's quite a useful page to
find out more information about
activities, and there's also the
tutorials on the Android developer site.
So you may find the one on Recreating
the activity after the system's
destroyed it, useful, and I'll give you
the link for that one.
That's also got some good information,
but lots of good information on that
page as well. And currently, the code
snippets are only showing in Java, but
I'm sure over time they'll update this to
show both Java and Kotlin examples. But
the documents are well worth reading, all
the same. So happy reading
and I'll see you in the next video.