1
00:00:03,650 --> 00:00:06,689
So this video will be a challenge to fix

2
00:00:06,689 --> 00:00:09,030
a bug in the calculator app, so we're

3
00:00:09,030 --> 00:00:11,250
gonna start by demonstrating that bug. So

4
00:00:11,250 --> 00:00:12,570
you can see that I've got the calculator

5
00:00:12,570 --> 00:00:14,969
app running on an emulator. Now the way

6
00:00:14,969 --> 00:00:17,789
that this app works, the arithmetic

7
00:00:17,789 --> 00:00:20,609
operation keys will cause the previous

8
00:00:20,609 --> 00:00:22,650
calculation to be performed, and then

9
00:00:22,650 --> 00:00:24,269
become the next operation to be

10
00:00:24,269 --> 00:00:26,189
performed. So this is done by storing

11
00:00:26,189 --> 00:00:28,560
the operation in the pendingOperation

12
00:00:28,560 --> 00:00:30,840
variable - as we saw when writing the code

13
00:00:30,840 --> 00:00:32,820
in previous videos. Now if you

14
00:00:32,820 --> 00:00:34,800
accidentally press an incorrect

15
00:00:34,800 --> 00:00:37,320
operation key when the input is empty,

16
00:00:37,320 --> 00:00:39,270
you can correct it by pressing the

17
00:00:39,270 --> 00:00:42,180
correct one - and you can see the

18
00:00:42,180 --> 00:00:43,890
operation change on the screen as I

19
00:00:43,890 --> 00:00:46,590
press each one. So to see the bug, I'm

20
00:00:46,590 --> 00:00:48,120
starting afresh so I don't need to clear

21
00:00:48,120 --> 00:00:50,430
anything, but just to make sure, I'm going

22
00:00:50,430 --> 00:00:52,379
to press, to clear rather, the pending

23
00:00:52,379 --> 00:00:54,989
operation by pressing equals. Then I'm

24
00:00:54,989 --> 00:01:02,059
going to enter 57 equals, then minus 6,

25
00:01:02,059 --> 00:01:08,159
and then multiply. So the result of 51 is

26
00:01:08,159 --> 00:01:10,260
displayed, and the next number that I

27
00:01:10,260 --> 00:01:14,130
enter should multiply 51. But, before

28
00:01:14,130 --> 00:01:15,479
entering another number, I'm going to

29
00:01:15,479 --> 00:01:16,979
rotate the device. So I'm gonna go into

30
00:01:16,979 --> 00:01:21,000
landscape mode. Now if I want to multiply

31
00:01:21,000 --> 00:01:24,869
51 by 2, I should just be able to do 2

32
00:01:24,869 --> 00:01:29,700
equals - so 2 equals. Now that didn't go well.

33
00:01:29,700 --> 00:01:32,009
So the problem is that although the

34
00:01:32,009 --> 00:01:34,439
contents of the EditText widget

35
00:01:34,439 --> 00:01:36,689
survive a rotation, none of the app's

36
00:01:36,689 --> 00:01:39,360
variables do. So the activity is

37
00:01:39,360 --> 00:01:42,119
destroyed and recreated when the device

38
00:01:42,119 --> 00:01:44,250
is rotated, remember, so the pending

39
00:01:44,250 --> 00:01:46,740
Operation variable is reset to

40
00:01:46,740 --> 00:01:50,189
equals. Alright, so the challenge is to

41
00:01:50,189 --> 00:01:52,290
fix the bug, by storing and retrieving

42
00:01:52,290 --> 00:01:55,219
the app's state when the device is rotated.

43
00:01:55,219 --> 00:01:57,630
Now if you're not sure how to do this, or

44
00:01:57,630 --> 00:01:59,729
to how to approach it, review the last

45
00:01:59,729 --> 00:02:02,549
videos in section 5, where I discussed

46
00:02:02,549 --> 00:02:04,979
the Activity Lifecycle, and where we

47
00:02:04,979 --> 00:02:07,500
saved the contents of the TextView for

48
00:02:07,500 --> 00:02:09,750
the Button Click App. Alright, so pause

49
00:02:09,750 --> 00:02:12,120
the video here, and when you've had a go

50
00:02:12,120 --> 00:02:13,290
at that and you're ready to come back

51
00:02:13,290 --> 00:02:13,830
and see the

52
00:02:13,830 --> 00:02:15,810
solution, you can start the

53
00:02:15,810 --> 00:02:17,220
video and I'll go through and do that. So

54
00:02:17,220 --> 00:02:19,349
pause the video now.

55
00:02:19,349 --> 00:02:21,290
Alright, so let's look at the solution.

56
00:02:21,290 --> 00:02:24,060
So the methods we need to Override to

57
00:02:24,060 --> 00:02:26,700
store state are onSaveInstanceState

58
00:02:26,700 --> 00:02:29,370
and onRestoreInstanceState. And as

59
00:02:29,370 --> 00:02:30,959
a reminder, here's the Activity Lifecycle

60
00:02:30,959 --> 00:02:33,749
slide from section five.

61
00:02:33,749 --> 00:02:37,590
Now onSaveInstanceState is called if

62
00:02:37,590 --> 00:02:39,870
needed, when Android's about to destroy

63
00:02:39,870 --> 00:02:41,639
the Activity - as it does when the

64
00:02:41,639 --> 00:02:43,920
orientation changes. So now that we've

65
00:02:43,920 --> 00:02:46,379
created a separate layout for landscape

66
00:02:46,379 --> 00:02:49,019
mode, the reason why Android destroys and

67
00:02:49,019 --> 00:02:51,299
recreates the activity may make more

68
00:02:51,299 --> 00:02:53,310
sense now. And it's because it's an entire new

69
00:02:53,310 --> 00:02:55,889
layout that has to be applied, and the

70
00:02:55,889 --> 00:02:57,930
easiest and safest way to do that is to

71
00:02:57,930 --> 00:03:00,389
just start again. So with all these

72
00:03:00,389 --> 00:03:02,219
challenges, there's often more than one

73
00:03:02,219 --> 00:03:04,409
way to solve them. The real test here is

74
00:03:04,409 --> 00:03:05,189
Does it work?

75
00:03:05,189 --> 00:03:07,500
and definitely not Does your code look

76
00:03:07,500 --> 00:03:10,590
the same as mine? Alright, so state can

77
00:03:10,590 --> 00:03:12,810
be restored in either onCreate or on

78
00:03:12,810 --> 00:03:15,180
RestoreInstanceState, and I'm going to

79
00:03:15,180 --> 00:03:17,669
use onRestoreInstanceState. But if

80
00:03:17,669 --> 00:03:20,040
your solution used onCreate, that's fine.

81
00:03:20,040 --> 00:03:22,469
The reason I prefer not to restore state

82
00:03:22,469 --> 00:03:25,109
in there - in onCreate - is mainly

83
00:03:25,109 --> 00:03:27,209
because it's a good idea to keep the

84
00:03:27,209 --> 00:03:29,340
code in a separate method, just to keep

85
00:03:29,340 --> 00:03:32,340
things easier to understand. In addition,

86
00:03:32,340 --> 00:03:34,500
if you try to use the Bundle in

87
00:03:34,500 --> 00:03:36,389
onCreate, you have to check that it isn't

88
00:03:36,389 --> 00:03:36,900
null.

89
00:03:36,900 --> 00:03:39,329
Now if there was no saved state, then

90
00:03:39,329 --> 00:03:41,370
Bundle will be null there, whereas on

91
00:03:41,370 --> 00:03:43,229
RestoreInstanceState is only ever

92
00:03:43,229 --> 00:03:44,759
called if there is a valid bundle.

93
00:03:44,759 --> 00:03:46,859
Alright, so let's go back to Android

94
00:03:46,859 --> 00:03:48,780
Studio for my solution to fixing this

95
00:03:48,780 --> 00:03:50,260
bug.

96
00:03:50,260 --> 00:03:52,900
Alright, so a bundle contains a list of

97
00:03:52,900 --> 00:03:55,810
pairs of keys and values, so we need keys

98
00:03:55,810 --> 00:03:57,849
to store the pendingOperation and

99
00:03:57,849 --> 00:04:00,519
operand1 variables under, to enable us to

100
00:04:00,519 --> 00:04:02,620
get them back again. Now because we'll be

101
00:04:02,620 --> 00:04:04,239
using the same keys in two different

102
00:04:04,239 --> 00:04:06,970
places, I'm gonna store them in two constants.

103
00:04:06,970 --> 00:04:09,580
Now unlike Java, where everything must

104
00:04:09,580 --> 00:04:12,190
exist inside a class, Kotlin allows

105
00:04:12,190 --> 00:04:14,379
variables to be declared at the top level

106
00:04:14,379 --> 00:04:17,139
of the file, outside of the class. In fact,

107
00:04:17,139 --> 00:04:19,540
for val constraints, it insists on this.

108
00:04:19,540 --> 00:04:21,820
So if I tried to put this next piece of

109
00:04:21,820 --> 00:04:23,560
code that I'm about to type, inside the

110
00:04:23,560 --> 00:04:25,479
MainActivity class, we'd actually get

111
00:04:25,479 --> 00:04:27,190
an error. Alright, so let's go back up

112
00:04:27,190 --> 00:04:30,280
to the top of MainActivity, and we want

113
00:04:30,280 --> 00:04:31,919
to put this before the class definition. So

114
00:04:31,919 --> 00:04:35,320
I'm gonna start on line 10, and I'm going

115
00:04:35,320 --> 00:04:39,010
to type private const val, and in

116
00:04:39,010 --> 00:04:42,240
uppercase, STATE_PENDING

117
00:04:42,240 --> 00:04:45,820
_OPERATION is equal to, and in

118
00:04:45,820 --> 00:04:50,380
double quotes, PendingOperation. Then

119
00:04:50,380 --> 00:04:56,979
private Const val STATE_

120
00:04:56,979 --> 00:05:00,340
OPERAND1 equal to, double quotes 

121
00:05:00,340 --> 00:05:01,889
Operand1.

122
00:05:01,889 --> 00:05:04,389
Now the actual contents of those strings

123
00:05:04,389 --> 00:05:06,160
can be pretty much anything, but there's

124
00:05:06,160 --> 00:05:08,050
a limit to how big a bundle can be, so

125
00:05:08,050 --> 00:05:10,419
don't go using incredibly long strings.

126
00:05:10,419 --> 00:05:12,820
And just in case it wasn't obvious when

127
00:05:12,820 --> 00:05:15,130
we discussed this earlier, data is saved

128
00:05:15,130 --> 00:05:17,950
in a Bundle as key/value pairs. So the

129
00:05:17,950 --> 00:05:19,360
keys we'll be using are these two

130
00:05:19,360 --> 00:05:21,370
constants; STATE_PENDING

131
00:05:21,370 --> 00:05:23,380
_OPERATION and STATE_

132
00:05:23,380 --> 00:05:25,599
OPERAND1. Now when we want to get

133
00:05:25,599 --> 00:05:27,669
the value for operand1, we use the key

134
00:05:27,669 --> 00:05:29,889
STATE_OPERAND1 to

135
00:05:29,889 --> 00:05:31,810
retrieve it, and similarly for the

136
00:05:31,810 --> 00:05:34,419
pending operation. Now saving the

137
00:05:34,419 --> 00:05:36,639
variables is just a case of overriding

138
00:05:36,639 --> 00:05:39,160
onSaveInstanceState using the

139
00:05:39,160 --> 00:05:42,099
shortcut Ctrl-O, or you can get a list of

140
00:05:42,099 --> 00:05:43,630
methods to override from Generate on

141
00:05:43,630 --> 00:05:45,340
the Code menu. Now I'm going to put the

142
00:05:45,340 --> 00:05:47,260
overridden methods at the end of

143
00:05:47,260 --> 00:05:49,180
the code, but before the final curly

144
00:05:49,180 --> 00:05:52,780
brace. I'm gonna go right down to the bottom, just down

145
00:05:52,780 --> 00:05:57,639
here, and I'm going to do a Ctrl-O, and we

146
00:05:57,639 --> 00:05:59,080
want onSaveInstanceState. So I'm just

147
00:05:59,080 --> 00:06:00,250
going to type the first few letters -

148
00:06:00,250 --> 00:06:02,770
onSave. There it is there, onSaveInstance

149
00:06:02,770 --> 00:06:03,760
State, so I'm just going to press 

150
00:06:03,760 --> 00:06:06,430
Enter. But before I do that, do be

151
00:06:06,430 --> 00:06:08,260
careful here, because there's two

152
00:06:08,260 --> 00:06:10,960
versions of this function. We want the

153
00:06:10,960 --> 00:06:12,430
one that takes a single argument,

154
00:06:12,430 --> 00:06:14,800
and unfortunately, that appears further

155
00:06:14,800 --> 00:06:16,870
down the list than the one that we don't

156
00:06:16,870 --> 00:06:18,190
want - the one that I've actually

157
00:06:18,190 --> 00:06:20,050
currently highlighted. So I'm going to

158
00:06:20,050 --> 00:06:21,490
use the down arrow key to move to the

159
00:06:21,490 --> 00:06:24,760
second definition. So you can see the

160
00:06:24,760 --> 00:06:25,990
second definition there, has only got

161
00:06:25,990 --> 00:06:28,540
just the one argument - outState, which is a

162
00:06:28,540 --> 00:06:33,360
Bundle. Alright, I'm gonna press Enter. And

163
00:06:33,360 --> 00:06:35,680
there's a slight oddity about this

164
00:06:35,680 --> 00:06:37,690
function, to do with the interoperability

165
00:06:37,690 --> 00:06:39,850
with Java, and I'm gonna come back to

166
00:06:39,850 --> 00:06:42,400
that in a minute. But first we need to

167
00:06:42,400 --> 00:06:44,800
add our variables to the bundle, so the

168
00:06:44,800 --> 00:06:46,570
overridden function is going to become

169
00:06:46,570 --> 00:06:48,340
as follows; so we're gonna leave the

170
00:06:48,340 --> 00:06:49,870
first call to super.onSave

171
00:06:49,870 --> 00:06:51,730
InstanceState. And then we're going to

172
00:06:51,730 --> 00:06:56,410
append to that, if parentheses operand

173
00:06:56,410 --> 00:07:02,050
one is not equal to null, in code block.

174
00:07:02,050 --> 00:07:05,800
We're going to do outState.put

175
00:07:05,800 --> 00:07:08,920
Double parentheses, and it's going to be

176
00:07:08,920 --> 00:07:10,810
STATE_OPERAND1 comma

177
00:07:10,810 --> 00:07:14,740
space and operand1 and bang bang - so

178
00:07:14,740 --> 00:07:18,250
two exclamation marks. Now we actually get

179
00:07:18,250 --> 00:07:19,660
an error there - we'll talk about that

180
00:07:19,660 --> 00:07:21,700
shortly. And then I'm going to put on the

181
00:07:21,700 --> 00:07:23,680
line after, outside the closing code

182
00:07:23,680 --> 00:07:28,300
block, outState.putString and STATE

183
00:07:28,300 --> 00:07:31,390
_PENDING_OPERATION comma

184
00:07:31,390 --> 00:07:34,780
space pendingOperation. So notice that

185
00:07:34,780 --> 00:07:36,520
we have to check, firstly, that operand

186
00:07:36,520 --> 00:07:38,770
1 isn't null, otherwise the program would

187
00:07:38,770 --> 00:07:41,020
crash if the device is rotated, before

188
00:07:41,020 --> 00:07:42,910
any numbers had been entered. Alright,

189
00:07:42,910 --> 00:07:44,560
so we've got this error at the moment, on

190
00:07:44,560 --> 00:07:47,950
line 113. And if we hover over that;

191
00:07:47,950 --> 00:07:50,470
Only safe or none-null asserted calls are

192
00:07:50,470 --> 00:07:52,630
allowed on a nullable receiver of type

193
00:07:52,630 --> 00:07:53,370
Bundle.

194
00:07:53,370 --> 00:07:56,020
Now if you haven't got that error, please

195
00:07:56,020 --> 00:07:57,430
keep watching and I'm going to explain

196
00:07:57,430 --> 00:08:00,220
why you haven't. So the problem is that

197
00:08:00,220 --> 00:08:03,250
the outState parameter is of type

198
00:08:03,250 --> 00:08:05,620
Bundle? which is a nullable

199
00:08:05,620 --> 00:08:08,140
Bundle. Now Kotlin doesn't allow method

200
00:08:08,140 --> 00:08:09,820
calls to be made on objects that could

201
00:08:09,820 --> 00:08:11,770
be null. That's a classic problem that

202
00:08:11,770 --> 00:08:13,750
causes Null Pointer Exceptions, and

203
00:08:13,750 --> 00:08:16,300
Kotlin actually makes sure we don't get

204
00:08:16,300 --> 00:08:17,470
those anymore - or at least

205
00:08:17,470 --> 00:08:19,600
it does its best. We can still get them

206
00:08:19,600 --> 00:08:21,160
if we go using the bang bang operator,

207
00:08:21,160 --> 00:08:22,960
which we shouldn't, for example.

208
00:08:22,960 --> 00:08:25,720
So using bang bang is one possible

209
00:08:25,720 --> 00:08:28,060
solution. So in other words, I could come

210
00:08:28,060 --> 00:08:33,280
back up to here, two exclamation marks -

211
00:08:33,280 --> 00:08:35,140
the bang bang. But what we're doing is

212
00:08:35,140 --> 00:08:38,020
asserting that outState won't be null.

213
00:08:38,020 --> 00:08:40,120
Can we be really sure that it can't be

214
00:08:40,120 --> 00:08:42,700
null? Well actually, yes we can. The reason

215
00:08:42,700 --> 00:08:45,220
is that onSaveInstanceState is only

216
00:08:45,220 --> 00:08:47,680
called if there's a Bundle to save. In

217
00:08:47,680 --> 00:08:49,510
fact, you may well not have that error.

218
00:08:49,510 --> 00:08:52,960
Google are adding the @NonNull

219
00:08:52,960 --> 00:08:55,060
annotations to the Android framework

220
00:08:55,060 --> 00:08:57,550
code all the time. And if they mark out

221
00:08:57,550 --> 00:09:00,340
State as NonNull, then Kotlin will be able to

222
00:09:00,340 --> 00:09:02,620
use a non-nullable Bundle type, instead

223
00:09:02,620 --> 00:09:04,270
of this Bundle? that it's

224
00:09:04,270 --> 00:09:08,140
using as the argument on line 110. So

225
00:09:08,140 --> 00:09:10,600
bang bang is one option, but Kotlin also

226
00:09:10,600 --> 00:09:12,550
provides another operator, that I think's

227
00:09:12,550 --> 00:09:14,770
more appropriate here. So let's go

228
00:09:14,770 --> 00:09:17,050
back and replace the double bang with a

229
00:09:17,050 --> 00:09:19,540
safe call operator, which is the question

230
00:09:19,540 --> 00:09:21,040
mark. So we're gonna go back and delete

231
00:09:21,040 --> 00:09:23,200
that - the bang bang - and replace that with

232
00:09:23,200 --> 00:09:25,870
the question mark. So that also fixes the

233
00:09:25,870 --> 00:09:27,910
error, and actually is a safer way to

234
00:09:27,910 --> 00:09:30,520
deal with this. So that applies probably

235
00:09:30,520 --> 00:09:32,560
everywhere that you're accessing a

236
00:09:32,560 --> 00:09:34,690
property or calling a method, on an

237
00:09:34,690 --> 00:09:37,210
object that's of a nullable type. So

238
00:09:37,210 --> 00:09:39,430
whereas bang bang asserts that the

239
00:09:39,430 --> 00:09:41,920
object can't be null, and throws an

240
00:09:41,920 --> 00:09:43,900
exception if it is, the safe call

241
00:09:43,900 --> 00:09:46,030
operator won't actually make the call if

242
00:09:46,030 --> 00:09:48,400
the object is null. So in our code here,

243
00:09:48,400 --> 00:09:50,710
putDouble just won't be called if out

244
00:09:50,710 --> 00:09:52,870
State is null. So that line will just do

245
00:09:52,870 --> 00:09:56,170
nothing. So that's a safer solution than

246
00:09:56,170 --> 00:09:58,210
the double bang operator, and I suggest

247
00:09:58,210 --> 00:10:00,280
you try to use the safe call operator in

248
00:10:00,280 --> 00:10:02,530
these situations. Now it doesn't really

249
00:10:02,530 --> 00:10:04,990
matter here, because we know that out

250
00:10:04,990 --> 00:10:07,510
State won't be null, but safe call can be

251
00:10:07,510 --> 00:10:09,700
used even when you can't be sure. And

252
00:10:09,700 --> 00:10:11,800
we'll see that used again throughout the

253
00:10:11,800 --> 00:10:13,720
course so, you'll get a feel for when

254
00:10:13,720 --> 00:10:15,820
it's a good way to deal with nullable

255
00:10:15,820 --> 00:10:18,490
objects. Okay, so there's a third approach

256
00:10:18,490 --> 00:10:20,680
that can be used here. Now before I

257
00:10:20,680 --> 00:10:22,839
change the code to use it, I should

258
00:10:22,839 --> 00:10:24,190
really point out that you need to

259
00:10:24,190 --> 00:10:26,380
be very careful when using this approach.

260
00:10:26,380 --> 00:10:28,089
So don't go using this approach

261
00:10:28,089 --> 00:10:29,260
indiscriminately.

262
00:10:29,260 --> 00:10:30,940
You need to be very sure that you

263
00:10:30,940 --> 00:10:31,329
understand

264
00:10:31,329 --> 00:10:33,399
what you're doing. So what I'm going

265
00:10:33,399 --> 00:10:36,579
to do is modify the function signature,

266
00:10:36,579 --> 00:10:39,579
so that it accepts a non-null Bundle

267
00:10:39,579 --> 00:10:41,980
argument. So the way to do that is to get

268
00:10:41,980 --> 00:10:45,220
rid of the question mark from the Bundle

269
00:10:45,220 --> 00:10:48,790
type, and once I've done that, I can

270
00:10:48,790 --> 00:10:51,489
actually get rid of the safe, the safe

271
00:10:51,489 --> 00:10:55,449
call operator, like so. Now I can't

272
00:10:55,449 --> 00:10:57,309
predict the future, but it wouldn't

273
00:10:57,309 --> 00:10:59,199
surprise me if this function signature

274
00:10:59,199 --> 00:11:01,569
gets generated automatically, before too

275
00:11:01,569 --> 00:11:03,970
long. It may even be the code that you've

276
00:11:03,970 --> 00:11:05,319
got, if you're watching this video

277
00:11:05,319 --> 00:11:08,470
sometime after I recorded it. As I said,

278
00:11:08,470 --> 00:11:09,879
you do need to be careful when using

279
00:11:09,879 --> 00:11:12,009
this, though. If you're absolutely sure

280
00:11:12,009 --> 00:11:14,379
that outState really will be an

281
00:11:14,379 --> 00:11:16,869
non-nullable type, then this is perfectly

282
00:11:16,869 --> 00:11:18,910
valid. But changing the function

283
00:11:18,910 --> 00:11:21,339
signatures of overridden methods mustn't

284
00:11:21,339 --> 00:11:23,259
be done without fully understanding what

285
00:11:23,259 --> 00:11:26,589
you're doing. So this is the approach I'm

286
00:11:26,589 --> 00:11:29,290
going to take in this app. Now one reason

287
00:11:29,290 --> 00:11:30,879
is that you'll already find code like

288
00:11:30,879 --> 00:11:33,009
this out there. People are already doing

289
00:11:33,009 --> 00:11:34,509
this, and although I haven't yet found an

290
00:11:34,509 --> 00:11:37,029
example of Google doing it, with onSave

291
00:11:37,029 --> 00:11:38,769
InstanceState, there may well be

292
00:11:38,769 --> 00:11:40,419
examples by the time you watch this

293
00:11:40,419 --> 00:11:44,169
video. Now restoring the variable is done

294
00:11:44,169 --> 00:11:46,419
by reading it from a bundle, and I'm also

295
00:11:46,419 --> 00:11:48,369
going to update the display so that the

296
00:11:48,369 --> 00:11:50,579
user can see which operation is pending.

297
00:11:50,579 --> 00:11:53,379
Once again, though, be careful, because

298
00:11:53,379 --> 00:11:55,629
there's an overloaded version of the on

299
00:11:55,629 --> 00:11:58,149
RestoreInstanceState method too. So we

300
00:11:58,149 --> 00:11:59,410
want the one that accepts a single

301
00:11:59,410 --> 00:12:01,360
Bundle argument, and I'm just going to

302
00:12:01,360 --> 00:12:03,579
generate it, just after this onSave

303
00:12:03,579 --> 00:12:06,669
InstanceState function. Let's go ahead

304
00:12:06,669 --> 00:12:11,919
and do that, doing a search for onRestore

305
00:12:11,919 --> 00:12:14,379
and notice we've got the two definitions

306
00:12:14,379 --> 00:12:15,819
there. We actually want the top one - the one

307
00:12:15,819 --> 00:12:17,410
that's just got the Bundle argument and

308
00:12:17,410 --> 00:12:19,839
not the second argument. So I'm going to

309
00:12:19,839 --> 00:12:22,209
press ENTER there. And what I'm going to

310
00:12:22,209 --> 00:12:25,059
do here is take the same approach as for

311
00:12:25,059 --> 00:12:27,160
onSaveInstanceState, and change the

312
00:12:27,160 --> 00:12:30,009
parameter to be a non-nullable Bundle. So

313
00:12:30,009 --> 00:12:32,199
we're going to get rid of the question

314
00:12:32,199 --> 00:12:36,790
mark on the type. Alright, so after the

315
00:12:36,790 --> 00:12:39,160
super.onRestoreInstanceState line,

316
00:12:39,160 --> 00:12:41,740
we need to restore our two properties

317
00:12:41,740 --> 00:12:43,000
from the Bundle,

318
00:12:43,000 --> 00:12:45,250
and then display the operation in its

319
00:12:45,250 --> 00:12:47,350
TextView. So I'm going to start by

320
00:12:47,350 --> 00:12:51,190
typing operand1 is equal to saved

321
00:12:51,190 --> 00:12:56,410
InstanceState.getDouble, and the

322
00:12:56,410 --> 00:12:57,490
argument's gonna be STATE

323
00:12:57,490 --> 00:13:00,450
_OPERAND1 for our const. And

324
00:13:00,450 --> 00:13:05,380
then pendingOperation equals saved

325
00:13:05,380 --> 00:13:09,430
InstanceState.getString, and the

326
00:13:09,430 --> 00:13:10,960
argument is STATE_PENDING

327
00:13:10,960 --> 00:13:13,810
_OPERATION, our constant definition. Then

328
00:13:13,810 --> 00:13:15,070
lastly, as I mentioned, we're going to

329
00:13:15,070 --> 00:13:16,450
display the operation. So it's going to

330
00:13:16,450 --> 00:13:20,100
be displayOperation.text is equal to

331
00:13:20,100 --> 00:13:23,470
pendingOperation. Now that looks fairly

332
00:13:23,470 --> 00:13:25,780
straightforward, but it's important to

333
00:13:25,780 --> 00:13:27,550
check the documentation for any methods

334
00:13:27,550 --> 00:13:29,140
that you use, so that you really

335
00:13:29,140 --> 00:13:31,750
understand how they behave. Now we can do

336
00:13:31,750 --> 00:13:33,910
that in Android Studio, by clicking on

337
00:13:33,910 --> 00:13:35,230
the function that we're interested in,

338
00:13:35,230 --> 00:13:37,750
and using Ctrl-Q on Windows or Linux, and

339
00:13:37,750 --> 00:13:40,240
on a Mac, it's actually Ctrl-J. So we're gonna go

340
00:13:40,240 --> 00:13:42,930
ahead and do that - and this is for the get

341
00:13:42,930 --> 00:13:46,690
Double. And we're gonna come up here and

342
00:13:46,690 --> 00:13:48,850
press my key, and there's the

343
00:13:48,850 --> 00:13:50,770
documentation that's popped up. Again,

344
00:13:50,770 --> 00:13:52,720
it's a Ctrl-Q on Windows or Linux, or

345
00:13:52,720 --> 00:13:56,110
Ctrl-J on a Mac. So the documentation is

346
00:13:56,110 --> 00:13:58,240
short, but it does state that the

347
00:13:58,240 --> 00:14:01,210
function will return 0.0 if the key

348
00:14:01,210 --> 00:14:03,400
doesn't exist in the Bundle. Well

349
00:14:03,400 --> 00:14:07,180
actually, it says or 0.0 if no mapping of

350
00:14:07,180 --> 00:14:08,890
the desired type exists for the given

351
00:14:08,890 --> 00:14:11,080
key, which essentially, means the same

352
00:14:11,080 --> 00:14:13,420
thing. So if a key with the value of

353
00:14:13,420 --> 00:14:15,490
STATE_OPERAND1 doesn't

354
00:14:15,490 --> 00:14:17,530
exist in the Bundle, or if it does exist

355
00:14:17,530 --> 00:14:19,720
but its value isn't a Double, then

356
00:14:19,720 --> 00:14:22,450
operand1 will be given the value 0.0.

357
00:14:22,450 --> 00:14:24,700
Well, that's not actually quite what we

358
00:14:24,700 --> 00:14:27,280
want. If we haven't stored operand1,

359
00:14:27,280 --> 00:14:29,920
that's because it was null, not because it

360
00:14:29,920 --> 00:14:32,530
was zero. So we do want it to have the value

361
00:14:32,530 --> 00:14:34,870
of null after calling getDouble, if it

362
00:14:34,870 --> 00:14:37,330
doesn't exist. Now we can provide a

363
00:14:37,330 --> 00:14:39,310
default value to the getDouble function,

364
00:14:39,310 --> 00:14:42,610
but unfortunately, that value can't be null.

365
00:14:42,610 --> 00:14:45,070
So the way that I suggest coping with

366
00:14:45,070 --> 00:14:46,870
storing values that may be null in a

367
00:14:46,870 --> 00:14:49,870
Bundle, is to also store a Boolean, to

368
00:14:49,870 --> 00:14:51,490
indicate if there's a value there or not.

369
00:14:51,490 --> 00:14:54,040
And that's probably easier to see than to

370
00:14:54,040 --> 00:14:56,450
describe, so let's get to the code.

371
00:14:56,450 --> 00:15:00,140
So firstly, we need to define another

372
00:15:00,140 --> 00:15:01,550
constant for the key, so I'll go right up

373
00:15:01,550 --> 00:15:03,730
to the top of the file to do that,

374
00:15:03,730 --> 00:15:05,750
remembering that the definition is above

375
00:15:05,750 --> 00:15:08,060
the class definition. This is going to be

376
00:15:08,060 --> 00:15:13,130
private const val. This one we'll call

377
00:15:13,130 --> 00:15:18,770
STATE_OPERAND1_STORED is equal to,

378
00:15:18,770 --> 00:15:20,870
and we'll call this one Operand1

379
00:15:20,870 --> 00:15:24,890
_Stored. So next we need to

380
00:15:24,890 --> 00:15:26,960
change the onSaveInstanceState

381
00:15:26,960 --> 00:15:28,250
function slightly, so let's go down to

382
00:15:28,250 --> 00:15:30,620
the bottom and do that. Now we need to

383
00:15:30,620 --> 00:15:32,300
add some code, so we've got this

384
00:15:32,300 --> 00:15:34,880
code on line 113 checking, to see if

385
00:15:34,880 --> 00:15:37,310
operand1 is not equal to null, and then

386
00:15:37,310 --> 00:15:39,590
we've got it putting a Double there. But what

387
00:15:39,590 --> 00:15:41,150
we're going to do after that line, is add

388
00:15:41,150 --> 00:15:45,410
a new line to put outState.put

389
00:15:45,410 --> 00:15:49,280
Boolean. Then we're going to put STATE_

390
00:15:49,280 --> 00:15:52,810
OPEERAND1_STORED comma true.

391
00:15:52,810 --> 00:15:54,920
So that's all we need to do for the

392
00:15:54,920 --> 00:15:56,540
onSaveInstanceState function.

393
00:15:56,540 --> 00:15:59,510
Now if operand1 was stored, we can check

394
00:15:59,510 --> 00:16:01,610
the value stored under the key STATE

395
00:16:01,610 --> 00:16:03,560
_OPERAND1_STORED.

396
00:16:03,560 --> 00:16:05,660
And if that's true, then we can call get

397
00:16:05,660 --> 00:16:07,880
Double, otherwise operand1 should be

398
00:16:07,880 --> 00:16:11,030
null. So let's update our onRestore

399
00:16:11,030 --> 00:16:13,160
InstanceState function. And we're going

400
00:16:13,160 --> 00:16:15,110
to make a change here, so after the super

401
00:16:15,110 --> 00:16:17,210
call, we're going to put a call here.

402
00:16:17,210 --> 00:16:19,810
We're going to put - type some code - if

403
00:16:19,810 --> 00:16:24,370
savedInstanceState.getBoolean

404
00:16:24,370 --> 00:16:27,560
STATE_OPERAND1_

405
00:16:27,560 --> 00:16:32,720
STORED comma space false. I'm going to

406
00:16:32,720 --> 00:16:34,730
open a code block. And what I'm going to

407
00:16:34,730 --> 00:16:36,860
do is put in this line here, this operand

408
00:16:36,860 --> 00:16:39,230
1 equals savedInstanceState.get

409
00:16:39,230 --> 00:16:41,570
Double. That will be in the if code block,

410
00:16:41,570 --> 00:16:44,710
and we'll also have an else here, else,

411
00:16:44,710 --> 00:16:48,980
another code block, operand1 is equal to

412
00:16:48,980 --> 00:16:56,330
null. So now on line 122, we call the get

413
00:16:56,330 --> 00:16:58,610
Boolean method, to retrieve the value

414
00:16:58,610 --> 00:17:00,800
stored with the key STATE_

415
00:17:00,800 --> 00:17:03,980
OPERAND1_STORED. The call to

416
00:17:03,980 --> 00:17:06,890
getBoolean includes a default value of

417
00:17:06,890 --> 00:17:09,410
false, so if the key isn't present, the

418
00:17:09,410 --> 00:17:10,530
condition will be false.

419
00:17:10,530 --> 00:17:12,780
So only if we saved true with that key,

420
00:17:12,780 --> 00:17:18,000
will line 123 be executed. Otherwise,

421
00:17:18,000 --> 00:17:19,740
operand1 will be set to null, as you

422
00:17:19,740 --> 00:17:22,980
can see on line 125. Now we can lift that

423
00:17:22,980 --> 00:17:24,720
assignment out of the if, just like we

424
00:17:24,720 --> 00:17:27,900
did earlier. If I click over here, I can

425
00:17:27,900 --> 00:17:29,760
click on that, and then the light bulb

426
00:17:29,760 --> 00:17:32,550
comes up and I can click on that. And notice

427
00:17:32,550 --> 00:17:34,020
that I only get that operation when I

428
00:17:34,020 --> 00:17:36,300
did click on that in the gutter. Notice

429
00:17:36,300 --> 00:17:38,280
there, that when I do that, if is

430
00:17:38,280 --> 00:17:39,990
underlined there. You see that just

431
00:17:39,990 --> 00:17:42,090
briefly, so, we could also have just clicked

432
00:17:42,090 --> 00:17:44,340
if to see that come up. We can come back

433
00:17:44,340 --> 00:17:48,690
over here again. There's the light bulb - 

434
00:17:48,690 --> 00:17:50,720
click on that, and lift ssignment out of if.

435
00:17:50,720 --> 00:17:52,980
And you can see the code's been changed

436
00:17:52,980 --> 00:17:55,970
for us. And that should now do it for us.

437
00:17:55,970 --> 00:17:58,890
So, let's actually run the app again and

438
00:17:58,890 --> 00:18:00,390
just check that it's actually working, as

439
00:18:00,390 --> 00:18:05,240
we suspect it will, or hope that it will.

440
00:18:05,240 --> 00:18:07,230
Alright, so I'm going to start by doing

441
00:18:07,230 --> 00:18:19,560
equals 57, equals minus 6, times. Now I'm

442
00:18:19,560 --> 00:18:23,070
going to rotate like I did last time, and

443
00:18:23,070 --> 00:18:27,360
then I'm going to type 2 equals. This

444
00:18:27,360 --> 00:18:29,910
time, we got the answer 102 so that's

445
00:18:29,910 --> 00:18:32,790
now working fine. So our calculator now

446
00:18:32,790 --> 00:18:35,040
behaves as expected, even when the

447
00:18:35,040 --> 00:18:37,530
orientation's changed. Now this particular

448
00:18:37,530 --> 00:18:40,320
app has very little state - there's just

449
00:18:40,320 --> 00:18:42,330
the contents of the two EditText widgets,

450
00:18:42,330 --> 00:18:44,730
the content of the displayOperation

451
00:18:44,730 --> 00:18:47,670
TextView, and operand1. Now the two

452
00:18:47,670 --> 00:18:49,410
EditText widgets are saved and

453
00:18:49,410 --> 00:18:52,050
restored for us. Android knows that users

454
00:18:52,050 --> 00:18:54,060
may type text into EditText widgets -

455
00:18:54,060 --> 00:18:55,830
that's what they're there for, after all -

456
00:18:55,830 --> 00:18:58,080
so the Activity's onSaveInstanceState

457
00:18:58,080 --> 00:19:00,330
and onRestoreInstanceState methods,

458
00:19:00,330 --> 00:19:02,430
are taking care of the EditText widgets.

459
00:19:02,430 --> 00:19:04,410
So that's why it's important, looking

460
00:19:04,410 --> 00:19:06,990
back at the code, to leave these super

461
00:19:06,990 --> 00:19:07,920
dot on calls,

462
00:19:07,920 --> 00:19:10,110
super.savedInstanceState on line

463
00:19:10,110 --> 00:19:12,030
112, and super.on

464
00:19:12,030 --> 00:19:16,140
RestoreInstanceState on line 121. So

465
00:19:16,140 --> 00:19:17,490
it's important to leave those in when we

466
00:19:17,490 --> 00:19:19,770
override the onSaveInstanceState and

467
00:19:19,770 --> 00:19:21,990
onRestoreInstanceState functions. So all

468
00:19:21,990 --> 00:19:23,400
we had to do was store and retrieve

469
00:19:23,400 --> 00:19:24,210
the contents of

470
00:19:24,210 --> 00:19:27,450
the TextView, and operand1. This was

471
00:19:27,450 --> 00:19:29,070
complicated slightly, because we're

472
00:19:29,070 --> 00:19:30,990
allowing operand1 to be null, and

473
00:19:30,990 --> 00:19:33,420
Kotlin can't store null in a Bundle. So

474
00:19:33,420 --> 00:19:35,520
we had to use that additional flag, to

475
00:19:35,520 --> 00:19:37,260
let us decide whether operand1 should

476
00:19:37,260 --> 00:19:39,900
be null, when we try to restore it. So

477
00:19:39,900 --> 00:19:41,250
there's still room for improvement, but

478
00:19:41,250 --> 00:19:43,380
before we change the way our Calculator

479
00:19:43,380 --> 00:19:45,180
works, we're going to look at another

480
00:19:45,180 --> 00:19:47,610
method that Kotlin provides, for getting

481
00:19:47,610 --> 00:19:49,710
references to widgets. And we'll do that

482
00:19:49,710 --> 00:19:52,580
in the next video.

