1
00:00:05,220 --> 00:00:06,080
All right, so we're now ready

2
00:00:06,080 --> 00:00:08,220
to start writing the code to make

3
00:00:08,220 --> 00:00:10,270
our calculator calculate.

4
00:00:10,270 --> 00:00:13,070
Now, we should have the calculator project open,

5
00:00:13,070 --> 00:00:15,890
we're gonna be editing MainActivity.kt,

6
00:00:15,890 --> 00:00:18,020
so what I'm gonna do is just to close down

7
00:00:18,020 --> 00:00:20,000
the ActivityMain, 'cause we don't really

8
00:00:20,000 --> 00:00:22,040
need that open any more,

9
00:00:22,040 --> 00:00:23,503
come over here and close that down,

10
00:00:23,503 --> 00:00:25,380
then we're gonna click on the Project pane

11
00:00:25,380 --> 00:00:28,080
and then we come down here and open the Package

12
00:00:28,080 --> 00:00:31,276
under app, java then the Package name,

13
00:00:31,276 --> 00:00:33,470
academy.learnprogramming.calculator,

14
00:00:33,470 --> 00:00:35,320
and double-click MainActivity.

15
00:00:35,320 --> 00:00:36,600
You wanna make sure also that you're

16
00:00:36,600 --> 00:00:39,050
also in the Android view.

17
00:00:39,050 --> 00:00:43,030
All right, so there's our class, our MainActivity.kt.

18
00:00:43,030 --> 00:00:44,980
Now, all the activity does at the moment

19
00:00:44,980 --> 00:00:47,037
is display the layout on the screen.

20
00:00:47,037 --> 00:00:49,380
Now that's taken care of by Android

21
00:00:49,380 --> 00:00:53,150
when we pass the layout's ID to SetContentView,

22
00:00:53,150 --> 00:00:54,543
here on line 10.

23
00:00:55,400 --> 00:00:57,800
Now, Android will then be watching the buttons

24
00:00:57,800 --> 00:01:00,200
but as we haven't attached any code to them,

25
00:01:00,200 --> 00:01:02,670
nothing will happen when we tap the buttons.

26
00:01:02,670 --> 00:01:05,810
Now, it's probably a good idea to think about

27
00:01:05,810 --> 00:01:06,910
what we want it to do,

28
00:01:06,910 --> 00:01:09,210
so let's actually have a look at some flowcharts

29
00:01:09,210 --> 00:01:11,253
describing how the app will work.

30
00:01:12,190 --> 00:01:14,150
Now, this is the main part of the programme,

31
00:01:14,150 --> 00:01:16,160
you can see on screen, and we've already

32
00:01:16,160 --> 00:01:19,000
got the code to display the layout on the screen.

33
00:01:19,000 --> 00:01:21,700
So it's that call to SetContentView

34
00:01:21,700 --> 00:01:25,280
that will display our activity called MainLayout.

35
00:01:25,280 --> 00:01:27,930
So next we need to perform some initialization,

36
00:01:27,930 --> 00:01:29,610
and this will find all the buttons

37
00:01:29,610 --> 00:01:31,500
that we're interested in, and then set

38
00:01:31,500 --> 00:01:33,380
their OnClick listener so that

39
00:01:33,380 --> 00:01:35,730
they actually do something when they're tapped.

40
00:01:37,000 --> 00:01:39,560
The programme will then wait, waking up each time

41
00:01:39,560 --> 00:01:42,030
the Android Framework calls one of the listeners

42
00:01:42,030 --> 00:01:44,550
that we've set, that's the button click process

43
00:01:44,550 --> 00:01:45,800
after the initialization.

44
00:01:46,850 --> 00:01:48,760
Now, once a button is clicked,

45
00:01:48,760 --> 00:01:51,530
we need to decide if it was one of the digit keys

46
00:01:51,530 --> 00:01:53,510
or the decimal point, in which case

47
00:01:53,510 --> 00:01:56,150
we just append it to the number on the screen,

48
00:01:56,150 --> 00:01:57,770
or if it represents an operation

49
00:01:57,770 --> 00:01:59,000
to perform on the numbers.

50
00:01:59,000 --> 00:02:02,525
Plus, minus, multiply, divide or equals.

51
00:02:02,525 --> 00:02:05,960
Now, the flowchart shows a decision being made there,

52
00:02:05,960 --> 00:02:09,729
but that's a representation of how the logic works

53
00:02:09,729 --> 00:02:11,680
and doesn't directly correspond

54
00:02:11,680 --> 00:02:13,310
to how we're gonna code it.

55
00:02:13,310 --> 00:02:15,410
In place of a test to see what kind of button

56
00:02:15,410 --> 00:02:18,230
was clicked, we're going to assign one or two

57
00:02:18,230 --> 00:02:21,770
different listeners to the different types of button.

58
00:02:21,770 --> 00:02:24,230
So the digits and decimal point buttons

59
00:02:24,230 --> 00:02:26,320
will have one OnClick listener

60
00:02:26,320 --> 00:02:29,360
and the operations button will have another.

61
00:02:29,360 --> 00:02:31,130
Now, the flowchart is accurate,

62
00:02:31,130 --> 00:02:33,550
but when you see one of those decision diamonds

63
00:02:33,550 --> 00:02:35,920
in a flowchart, you generally expect to see

64
00:02:35,920 --> 00:02:37,740
an if statement in the code,

65
00:02:37,740 --> 00:02:39,340
but we'll be implementing the decision

66
00:02:39,340 --> 00:02:43,080
by attaching different listeners to the buttons instead.

67
00:02:43,080 --> 00:02:45,690
Now, the digit and decimal point listener

68
00:02:45,690 --> 00:02:47,570
is going to be very simple.

69
00:02:47,570 --> 00:02:49,960
It just reads the caption on the button

70
00:02:49,960 --> 00:02:52,460
and appends it to the number that's being built up

71
00:02:52,460 --> 00:02:54,373
in the EditText on the screen.

72
00:02:55,220 --> 00:02:57,770
When one of the operation buttons is tapped,

73
00:02:57,770 --> 00:03:00,400
it'll just read the number from the EditText,

74
00:03:00,400 --> 00:03:03,340
then check to make sure there actually was a number there.

75
00:03:03,340 --> 00:03:06,210
If there isn't and the EditBox is empty,

76
00:03:06,210 --> 00:03:09,830
the operation is stored as a pending operation

77
00:03:09,830 --> 00:03:11,700
and the programme goes back to waiting

78
00:03:11,700 --> 00:03:13,870
for another button to be clicked.

79
00:03:13,870 --> 00:03:16,700
And it will also update the little TextView on the left

80
00:03:16,700 --> 00:03:19,660
with the symbol for the operation that was tapped,

81
00:03:19,660 --> 00:03:22,860
just to remind the user what arithmetic operation

82
00:03:22,860 --> 00:03:25,820
will be performed when they press the equals button.

83
00:03:25,820 --> 00:03:27,960
And if there was a number, the programme will perform

84
00:03:27,960 --> 00:03:29,830
whatever operation was pending,

85
00:03:29,830 --> 00:03:31,773
and then display the result.

86
00:03:32,660 --> 00:03:34,010
So as you can see on this slide,

87
00:03:34,010 --> 00:03:36,080
the programme will allow you to do things like

88
00:03:36,080 --> 00:03:39,410
three plus 50 minus two times eight,

89
00:03:39,410 --> 00:03:42,390
and update the result after each stage.

90
00:03:42,390 --> 00:03:44,720
So when you type the three, it will appear

91
00:03:44,720 --> 00:03:47,190
on the display, when you press plus,

92
00:03:47,190 --> 00:03:49,110
there's nothing to add to three so the

93
00:03:49,110 --> 00:03:51,660
pending operation becomes plus.

94
00:03:51,660 --> 00:03:53,763
Once you've entered 50, the minus button

95
00:03:53,763 --> 00:03:56,810
will cause the plus operation to be performed

96
00:03:56,810 --> 00:04:00,890
and the result, 53 in this case, will appear in the result.

97
00:04:00,890 --> 00:04:03,720
Now the pending operation will then be minus.

98
00:04:03,720 --> 00:04:06,750
After two is entered, the multiply button

99
00:04:06,750 --> 00:04:09,200
will cause the subtraction to be performed,

100
00:04:09,200 --> 00:04:11,210
the result of 42 will be displayed

101
00:04:11,210 --> 00:04:14,170
and the pending operation will then be multiply.

102
00:04:14,170 --> 00:04:17,130
And once eight is entered, nothing will happen

103
00:04:17,130 --> 00:04:19,839
until another operation key, including equals,

104
00:04:19,839 --> 00:04:22,870
is tapped, then the new result will be displayed.

105
00:04:22,870 --> 00:04:24,950
All right, so that looks fairly straightforward,

106
00:04:24,950 --> 00:04:27,113
so let's go and add the code.

107
00:04:28,450 --> 00:04:30,920
All right, so we're gonna start off with fields

108
00:04:30,920 --> 00:04:33,278
to hold the references to the three widgets

109
00:04:33,278 --> 00:04:35,770
that will be updated or read.

110
00:04:35,770 --> 00:04:38,120
And also some variables to store the operands

111
00:04:38,120 --> 00:04:40,830
and the pending operation.

112
00:04:40,830 --> 00:04:42,720
So let's go ahead and do that now.

113
00:04:42,720 --> 00:04:44,843
So we've got our various code in there,

114
00:04:44,843 --> 00:04:45,780
I'm just gonna expand the import

115
00:04:45,780 --> 00:04:47,620
so we can see what we're doing here,

116
00:04:47,620 --> 00:04:51,610
and just below to class activity line on line six,

117
00:04:51,610 --> 00:04:55,350
we're going to add a line here, it's gonna be private.

118
00:04:55,350 --> 00:04:58,480
Space var, result.

119
00:04:58,480 --> 00:05:01,063
Space, colon.

120
00:05:02,060 --> 00:05:04,563
In EditText, equals null.

121
00:05:06,500 --> 00:05:09,493
Now Android Studio's showing an error on line eight.

122
00:05:10,705 --> 00:05:12,480
If we hover over it, "Null can not be a value

123
00:05:12,480 --> 00:05:13,930
of a non-null type EditText."

124
00:05:15,220 --> 00:05:17,190
Now, Kotlin does this as much as possible

125
00:05:17,190 --> 00:05:19,890
to protect us from null pointer exceptions,

126
00:05:19,890 --> 00:05:23,012
and by default, properties and variables in Kotlin

127
00:05:23,012 --> 00:05:24,960
can't be null.

128
00:05:24,960 --> 00:05:26,550
Now that's really great for preventing

129
00:05:26,550 --> 00:05:28,650
null pointer exceptions, but it means

130
00:05:28,650 --> 00:05:31,340
that we have to change the way we think slightly,

131
00:05:31,340 --> 00:05:33,100
if you're used to Java.

132
00:05:33,100 --> 00:05:35,710
So, we can't just not initialise it

133
00:05:35,710 --> 00:05:37,580
because Kotlin won't allow that.

134
00:05:37,580 --> 00:05:39,070
So just to show that, if I remove

135
00:05:39,070 --> 00:05:41,213
the equals null on the endthere,

136
00:05:42,490 --> 00:05:44,790
we also get another error, "Property must be

137
00:05:44,790 --> 00:05:47,470
initialised or be abstract."

138
00:05:47,470 --> 00:05:50,050
Now, with a Java mindset, we could just

139
00:05:50,050 --> 00:05:52,770
declare result to be a nullable type,

140
00:05:52,770 --> 00:05:55,420
which we do by adding a question mark after the name.

141
00:05:55,420 --> 00:05:58,377
So I can come back here out of the EditText

142
00:05:58,377 --> 00:06:01,673
and put a question mark, and set that equal to null.

143
00:06:03,943 --> 00:06:06,310
And that indeed does get rid of the error,

144
00:06:06,310 --> 00:06:08,270
but now we lose all the protection

145
00:06:08,270 --> 00:06:11,437
from null pointer exceptions that Kotlin provides.

146
00:06:11,437 --> 00:06:16,080
Now, marking variables as nullable is sometimes valid

147
00:06:16,080 --> 00:06:18,090
and we're gonna be doing that shortly.

148
00:06:18,090 --> 00:06:20,440
But unless you've got a good reason for doing this,

149
00:06:20,440 --> 00:06:22,220
then it should be avoided.

150
00:06:22,220 --> 00:06:23,950
So the problem we've got is that we have to

151
00:06:23,950 --> 00:06:26,260
initialise result to something,

152
00:06:26,260 --> 00:06:29,200
but we can't get the reference to our EditText widget

153
00:06:29,200 --> 00:06:32,000
until the OnCreate method executes.

154
00:06:32,000 --> 00:06:35,020
Now, the Java solution of initialising it to null

155
00:06:35,020 --> 00:06:37,690
isn't actually good practise in Kotlin.

156
00:06:37,690 --> 00:06:40,680
Now, fortunately, the designers of the Kotlin language

157
00:06:40,680 --> 00:06:42,630
have thought of this, and they provided

158
00:06:42,630 --> 00:06:47,300
the lateinit keyword as one way to handle this situation.

159
00:06:47,300 --> 00:06:49,610
So what we can do is come back up here

160
00:06:49,610 --> 00:06:52,480
and for our definition, we can put private,

161
00:06:52,480 --> 00:06:54,823
and before the var, we'll put lateinit,

162
00:06:56,680 --> 00:06:58,900
their result in EditText, and I'll get rid

163
00:06:58,900 --> 00:07:02,115
of the question mark equals null on the end there.

164
00:07:02,115 --> 00:07:03,950
And you can see the error's disappeared there.

165
00:07:03,950 --> 00:07:06,060
And what that does, it tells Kotlin that

166
00:07:06,060 --> 00:07:08,490
we're using a non-nullable variable,

167
00:07:08,490 --> 00:07:11,530
but that we're gonna defer giving it a value until later.

168
00:07:11,530 --> 00:07:14,300
So lateinit, as you probably will have figured out,

169
00:07:14,300 --> 00:07:16,750
is short for late initialization.

170
00:07:16,750 --> 00:07:18,910
Now, if we attempt to use result

171
00:07:18,910 --> 00:07:22,510
before giving it a value, the app will actually crash.

172
00:07:22,510 --> 00:07:25,170
Now currently you'll get a Kotlin.unitialized

173
00:07:25,170 --> 00:07:27,130
property access defection.

174
00:07:27,130 --> 00:07:28,740
Although the documentation's a little bit vague

175
00:07:28,740 --> 00:07:30,340
about the exact exception,

176
00:07:30,340 --> 00:07:32,650
so we should probably rely on that exact exception

177
00:07:32,650 --> 00:07:34,730
in our code, but that's no problem,

178
00:07:34,730 --> 00:07:36,820
because you wouldn't want to catch that exception,

179
00:07:36,820 --> 00:07:40,090
you'd fix the problem after finding it during testing.

180
00:07:40,090 --> 00:07:42,550
Okay, so that's one way to solve the problem.

181
00:07:42,550 --> 00:07:44,760
And I'm going to use this same lateinit approach

182
00:07:44,760 --> 00:07:46,930
for the next widget, the other EditText,

183
00:07:46,930 --> 00:07:48,900
which I'm gonna call newNumber.

184
00:07:48,900 --> 00:07:52,613
Let's go and create that, so private, lateinit,

185
00:07:54,203 --> 00:07:58,343
var newNumber: and EditText again.

186
00:07:59,970 --> 00:08:03,330
So lateinit's very useful in cases like this,

187
00:08:03,330 --> 00:08:05,050
but keep in mind it can only be used

188
00:08:05,050 --> 00:08:07,130
with var properties, in other words,

189
00:08:07,130 --> 00:08:09,530
that's properties that are read and write.

190
00:08:09,530 --> 00:08:12,330
Now sometimes, that's fine, we may want to

191
00:08:12,330 --> 00:08:14,890
make result refer to different EditText widgets

192
00:08:14,890 --> 00:08:16,140
while the code runs.

193
00:08:16,140 --> 00:08:18,100
In that case, lateinit is probably

194
00:08:18,100 --> 00:08:19,590
the best way to define it.

195
00:08:19,590 --> 00:08:21,140
But in this app, the references to

196
00:08:21,140 --> 00:08:23,160
our widgets won't change,

197
00:08:23,160 --> 00:08:24,950
and that means that in Kotlin,

198
00:08:24,950 --> 00:08:27,180
we should consider declaring them as val,

199
00:08:27,180 --> 00:08:28,650
rather than var.

200
00:08:28,650 --> 00:08:29,960
If that doesn't mean much to you then

201
00:08:29,960 --> 00:08:33,460
review the Kotlin tutorials earlier in this course.

202
00:08:33,460 --> 00:08:35,971
All right, so another way to declare our widget references

203
00:08:35,971 --> 00:08:38,559
is to use a lazy delegate.

204
00:08:38,559 --> 00:08:40,039
So I'm gonna show you how to do that,

205
00:08:40,039 --> 00:08:42,380
we're gonna write some code now, on the next line,

206
00:08:42,380 --> 00:08:45,987
private val displayOperation by lazy,

207
00:08:49,460 --> 00:08:51,630
then we need left and right curly braces,

208
00:08:51,630 --> 00:08:53,880
and within them we're gonna put findViewByID,

209
00:08:54,789 --> 00:08:57,490
you have the parentheses, but before the parentheses,

210
00:08:57,490 --> 00:08:59,650
you wanna have two diamonds, or a diamond

211
00:08:59,650 --> 00:09:02,640
as you can see there, left and right signs,

212
00:09:02,640 --> 00:09:04,840
and then in there we're gonna type TextView,

213
00:09:06,480 --> 00:09:11,480
then in parentheses, we're gonna put r.id.operation,

214
00:09:14,200 --> 00:09:16,573
let's put a space there so it's a bit more readable.

215
00:09:17,929 --> 00:09:21,037
Now when using this by lazy, you're defining a function

216
00:09:21,037 --> 00:09:24,770
that'll be called to assign the value to the property.

217
00:09:24,770 --> 00:09:27,270
Now, the function will be called the first time

218
00:09:27,270 --> 00:09:30,670
that the property's accessed, then the value is cached,

219
00:09:30,670 --> 00:09:32,260
so that the function isn't called again.

220
00:09:32,260 --> 00:09:33,600
That's pretty cool.

221
00:09:33,600 --> 00:09:36,570
So, as long as we don't access DisplayOperation,

222
00:09:36,570 --> 00:09:40,000
until onCreate has been called, this'll work fine.

223
00:09:40,000 --> 00:09:42,270
And it has the advantage that DisplayOperation

224
00:09:42,270 --> 00:09:44,470
can be declared as val, which can make

225
00:09:44,470 --> 00:09:47,393
code more robust for properties that won't change.

226
00:09:48,468 --> 00:09:50,600
Now, there's no reason why I couldn't have used

227
00:09:50,600 --> 00:09:53,060
the same approach for all three variables,

228
00:09:53,060 --> 00:09:55,740
in fact, we probably should, 'cause there's no reason

229
00:09:55,740 --> 00:09:59,090
result and newNumber can't be declared as val.

230
00:09:59,090 --> 00:10:01,430
But I've done it this way to show you the options,

231
00:10:01,430 --> 00:10:03,530
and while you may have to use lateinit,

232
00:10:03,530 --> 00:10:06,040
rather than the lazy delegation.

233
00:10:06,040 --> 00:10:07,610
Now, there are other ways of handling this

234
00:10:07,610 --> 00:10:10,270
and we'll see another alternative shortly.

235
00:10:10,270 --> 00:10:13,090
Kotlin development for Android is still fairly new,

236
00:10:13,090 --> 00:10:14,560
and developers are still working out

237
00:10:14,560 --> 00:10:16,450
which approaches to settle on.

238
00:10:16,450 --> 00:10:17,900
Google for instance don't yet have

239
00:10:17,900 --> 00:10:19,491
a style guide for Kotlin, at least not

240
00:10:19,491 --> 00:10:21,950
at the time of recording this video.

241
00:10:21,950 --> 00:10:24,680
When they do, you'll probably be able to find it

242
00:10:24,680 --> 00:10:26,610
at this address, and I'm just going to put that

243
00:10:26,610 --> 00:10:27,640
on the screen there for you,

244
00:10:27,640 --> 00:10:29,640
well, I'll actually just open a browser.

245
00:10:31,710 --> 00:10:33,300
So when they do release one, which I'm sure

246
00:10:33,300 --> 00:10:36,160
they will in time, it'll probably be at this address.

247
00:10:36,160 --> 00:10:40,363
Github.com/google/styleguide, all one word.

248
00:10:41,300 --> 00:10:43,800
And you can see there, if we actually scroll down,

249
00:10:45,330 --> 00:10:47,530
there's various languages that they actually

250
00:10:48,863 --> 00:10:51,150
talk about in there, Java, C++, Python and so forth,

251
00:10:51,150 --> 00:10:52,490
but at the time I'm recording this,

252
00:10:52,490 --> 00:10:54,087
there isn't a guide for Kotlin.

253
00:10:55,850 --> 00:10:56,980
You can see there's nothing seems to be

254
00:10:56,980 --> 00:10:59,480
starting with Kotlin, I'll just do a quick search,

255
00:11:00,850 --> 00:11:02,820
nothing there, but I would say in time,

256
00:11:02,820 --> 00:11:04,170
almost certainly they will release

257
00:11:04,170 --> 00:11:05,980
a style guide for Kotlin.

258
00:11:07,111 --> 00:11:08,370
And once we've finished this app, what I'm gonna do

259
00:11:08,370 --> 00:11:10,340
is change it to use another way,

260
00:11:10,340 --> 00:11:11,930
then you'll see three different ways of

261
00:11:11,930 --> 00:11:13,520
dealing with this situation,

262
00:11:13,520 --> 00:11:15,420
and you can understand code regardless

263
00:11:15,420 --> 00:11:17,130
of the approach you use.

264
00:11:17,130 --> 00:11:19,710
Right, I'm just gonna go back to Android Studio.

265
00:11:19,710 --> 00:11:22,360
Now, one thing to note is that the lazy function

266
00:11:22,360 --> 00:11:23,830
is thread safe.

267
00:11:23,830 --> 00:11:26,905
That means that if the DisplayOperation property

268
00:11:26,905 --> 00:11:29,880
is accessed by code in two or more threads simultaneously,

269
00:11:29,880 --> 00:11:32,720
the function will still only be called once.

270
00:11:32,720 --> 00:11:34,570
Now, don't worry if that doesn't make sense,

271
00:11:34,570 --> 00:11:36,404
we'll be talking about background threads

272
00:11:36,404 --> 00:11:38,410
later in the course.

273
00:11:38,410 --> 00:11:40,530
For now though, it's enough to use the modified version

274
00:11:40,530 --> 00:11:42,350
that I'm just about to enter.

275
00:11:42,350 --> 00:11:44,670
Now, our activity class can't be accessed

276
00:11:44,670 --> 00:11:47,210
by more than one thread, so there's actually no need

277
00:11:47,210 --> 00:11:50,920
for the extra overhead that lazy includes by default.

278
00:11:50,920 --> 00:11:53,030
So, when you're just using it in an activity,

279
00:11:53,030 --> 00:11:54,930
as we are here, then you can add

280
00:11:54,930 --> 00:11:59,040
an extra parameter to disable the thread safe code.

281
00:11:59,040 --> 00:12:01,640
And I'm going to do that now, so after this by lazy,

282
00:12:02,715 --> 00:12:06,344
we put in parentheses, then we type in

283
00:12:06,344 --> 00:12:11,344
lazyThreadSafetyMode.none, or I'm choosing that

284
00:12:11,710 --> 00:12:13,140
from the drop-down.

285
00:12:13,140 --> 00:12:15,420
And everything else will be as it was before.

286
00:12:15,420 --> 00:12:17,020
Now as I said, don't worry too much

287
00:12:17,020 --> 00:12:19,480
about that at this stage, you probably do

288
00:12:19,480 --> 00:12:22,380
want to add that lazy threadSafetyMode.none argument

289
00:12:22,380 --> 00:12:25,090
to lazy whenever you're using it in an activity

290
00:12:25,090 --> 00:12:26,340
like we are here.

291
00:12:26,340 --> 00:12:28,690
And if you need thread safety in your properties,

292
00:12:28,690 --> 00:12:30,480
you'll know, and all of this will

293
00:12:30,480 --> 00:12:32,370
make a lot more sense later.

294
00:12:32,370 --> 00:12:34,900
All right, so moving on now, we also need

295
00:12:34,900 --> 00:12:37,710
to make some variables to store the numbers

296
00:12:37,710 --> 00:12:40,540
that we're gonna be using in our calculations.

297
00:12:40,540 --> 00:12:41,910
Let's go ahead and do that.

298
00:12:41,910 --> 00:12:43,460
And I'll just make a note here.

299
00:12:45,300 --> 00:12:49,470
I've put these outside variables to hold the operands

300
00:12:51,110 --> 00:12:52,633
and type of calculations.

301
00:12:56,860 --> 00:12:58,680
And the ones that we want here,

302
00:12:58,680 --> 00:13:03,680
private var operand1: Double, capital D,

303
00:13:06,560 --> 00:13:08,550
question mark equals null,

304
00:13:08,550 --> 00:13:09,510
and I'll just type the other two

305
00:13:09,510 --> 00:13:11,530
and then we'll talk about these.

306
00:13:11,530 --> 00:13:15,493
Private var again, operand 2, colon, this is also

307
00:13:15,493 --> 00:13:20,263
gonna be a Double, no question mark this time equals 0.0.

308
00:13:21,550 --> 00:13:24,300
Or a period, whatever you're used to calling it.

309
00:13:24,300 --> 00:13:28,637
Private var pendingOperation equals, in double quotes,

310
00:13:30,910 --> 00:13:31,853
an equals sign.

311
00:13:32,860 --> 00:13:34,710
Now, I mentioned earlier that we'd be looking at

312
00:13:34,710 --> 00:13:37,400
a nullable variable, and the declaration

313
00:13:37,400 --> 00:13:40,233
of operand1 shows how to specify that it can be null.

314
00:13:41,110 --> 00:13:42,740
To do that, you just put a question mark

315
00:13:42,740 --> 00:13:44,500
after its type, as you can see I've done there,

316
00:13:44,500 --> 00:13:46,260
on line 14.

317
00:13:46,260 --> 00:13:49,050
Now, the reason Why we're allowing operand1 to be null

318
00:13:49,050 --> 00:13:51,220
is that we need to record whether it's been given

319
00:13:51,220 --> 00:13:53,170
a value or not.

320
00:13:53,170 --> 00:13:54,900
Now, when the app's first started,

321
00:13:54,900 --> 00:13:57,370
there won't be a number to perform calculations on,

322
00:13:57,370 --> 00:13:59,510
and our app needs to allow for this,

323
00:13:59,510 --> 00:14:02,596
so that it knows when the number that the user enters

324
00:14:02,596 --> 00:14:06,060
is operand1, or operand2.

325
00:14:06,060 --> 00:14:09,140
Now, what a null value for operand1 signifies

326
00:14:09,140 --> 00:14:12,090
that the user hasn't yet given it a value.

327
00:14:12,090 --> 00:14:14,550
And you'll see how to make use of this in a moment.

328
00:14:14,550 --> 00:14:16,540
The important thing is that null is a valid

329
00:14:16,540 --> 00:14:19,360
type for operand1, so we're deliberately

330
00:14:19,360 --> 00:14:22,213
declaring it as a variable that can be null.

331
00:14:23,190 --> 00:14:26,490
Okay, so moving on now, to the OnCreate function,

332
00:14:26,490 --> 00:14:29,170
we need to find our widgets, and store the references

333
00:14:29,170 --> 00:14:31,580
to them in those three variables.

334
00:14:31,580 --> 00:14:34,800
And we also need to do that for the 16 buttons.

335
00:14:34,800 --> 00:14:36,870
So let's go ahead and do that now.

336
00:14:36,870 --> 00:14:39,650
So I'm going to add this code after the super.onCreate

337
00:14:39,650 --> 00:14:41,933
and after the SetContentView calls.

338
00:14:43,130 --> 00:14:45,800
So the first one is going to be result

339
00:14:45,800 --> 00:14:49,850
is equal to findViewbyId, that's gonna be

340
00:14:49,850 --> 00:14:52,690
r.id.result, as you can see,

341
00:14:52,690 --> 00:14:54,840
I'm selecting from the drop-downs.

342
00:14:54,840 --> 00:14:59,840
Then newNumber, that's equal to findViewById,

343
00:15:00,000 --> 00:15:03,090
and that's gonna be r.id.newNumber,

344
00:15:03,090 --> 00:15:05,520
again, we're using the IDs that we defined

345
00:15:05,520 --> 00:15:07,370
when we were creating our layout.

346
00:15:07,370 --> 00:15:10,950
So next we need to add definitions

347
00:15:10,950 --> 00:15:12,513
for our data input buttons.

348
00:15:14,930 --> 00:15:16,903
So I'm just adding a comment to that effect.

349
00:15:17,760 --> 00:15:22,090
We start with val, button0, colon,

350
00:15:22,090 --> 00:15:25,630
Button with a capital B equals findViewById, r.id

351
00:15:27,460 --> 00:15:29,590
And it should be button zero.

352
00:15:29,590 --> 00:15:32,220
Then what I'm going to do is just copy

353
00:15:32,220 --> 00:15:35,320
one for the rest, so button one, two, three, four,

354
00:15:35,320 --> 00:15:37,160
five, six, seven, eight, nine,

355
00:15:37,160 --> 00:15:40,060
we'll also do the dot, so let's go ahead and change those.

356
00:15:47,270 --> 00:15:49,170
And the last one we'll call buttonDot,

357
00:15:52,570 --> 00:15:57,339
and this is gonna be then nine, eight, seven, six,

358
00:15:57,339 --> 00:16:02,310
five, four, three, two and one.

359
00:16:02,310 --> 00:16:03,620
Now you'll know if you made a mistake there,

360
00:16:03,620 --> 00:16:05,430
because if we typed something that doesn't exist,

361
00:16:05,430 --> 00:16:07,350
you 'll get this red flag.

362
00:16:07,350 --> 00:16:10,350
So these, getting these IDs and the IDs we defined

363
00:16:10,350 --> 00:16:12,080
when we were creating the layout

364
00:16:12,080 --> 00:16:14,139
earlier in this section of the course.

365
00:16:14,139 --> 00:16:16,839
All right, so that's our data input buttons there now,

366
00:16:17,972 --> 00:16:22,000
and we also need to store references to our

367
00:16:22,000 --> 00:16:23,720
operation buttons as well.

368
00:16:23,720 --> 00:16:26,105
So, let's make a comment about that,

369
00:16:26,105 --> 00:16:29,113
so, Operation, our son's, making a bit more space here.

370
00:16:34,200 --> 00:16:36,243
So we've got button equals.

371
00:16:40,019 --> 00:16:45,019
findViewById, and in the diamond I'm going to put button.

372
00:16:47,950 --> 00:16:52,950
Subtitle button, that's gotta be r.id.as a button equals.

373
00:16:55,950 --> 00:16:58,640
Let's do the same for the divide button.

374
00:16:58,640 --> 00:17:00,313
Multiply minus and plus.

375
00:17:03,172 --> 00:17:04,992
So, first one is going to be divide,

376
00:17:09,579 --> 00:17:12,853
divide, next one, we'll do multiply.

377
00:17:15,700 --> 00:17:17,089
Let's just do these last two as well.

378
00:17:17,089 --> 00:17:20,150
We also want the minus and then

379
00:17:20,150 --> 00:17:21,400
finish off with the plus.

380
00:17:22,900 --> 00:17:25,400
And on the left-hand side, let's fix that as well.

381
00:17:27,220 --> 00:17:28,903
So plus will be the first one,

382
00:17:30,740 --> 00:17:31,893
minus for the next one,

383
00:17:33,950 --> 00:17:37,637
Then multiply, and that should be it.

384
00:17:37,637 --> 00:17:41,060
So we've got equals, divide, multiply, minus and plus,

385
00:17:41,060 --> 00:17:43,170
and equals, divide, multiply, minus and plus

386
00:17:43,170 --> 00:17:44,320
on the right-hand side.

387
00:17:45,220 --> 00:17:47,530
And by the way, we're only referring to the button widgets

388
00:17:47,530 --> 00:17:50,700
inside this onCreate method, and so there's no need

389
00:17:50,700 --> 00:17:52,060
to create properties for them,

390
00:17:52,060 --> 00:17:53,980
and that's why we've done that as opposed

391
00:17:53,980 --> 00:17:55,560
to the other ones that we created our

392
00:17:55,560 --> 00:17:58,313
properties outside, fix up that typo,

393
00:17:59,890 --> 00:18:01,750
outside the method.

394
00:18:01,750 --> 00:18:05,520
Now, we're using the Android findViewById function

395
00:18:05,520 --> 00:18:08,060
to get references to the widgets in the layout,

396
00:18:08,060 --> 00:18:09,570
but note that we don't need to do that

397
00:18:09,570 --> 00:18:11,360
for the operation widget.

398
00:18:11,360 --> 00:18:14,600
The findViewById function will be called the first time

399
00:18:14,600 --> 00:18:16,863
we access DisplayOperation, so we don't need

400
00:18:16,863 --> 00:18:19,560
to find it in our OnCreate function.

401
00:18:19,560 --> 00:18:22,490
And that's this lazy delegate function that

402
00:18:22,490 --> 00:18:24,940
we defined here on line 12.

403
00:18:24,940 --> 00:18:28,050
Basically, that's the lazy delegate at work.

404
00:18:28,050 --> 00:18:30,660
Now, blank lines in the code also help to separate

405
00:18:30,660 --> 00:18:32,870
the two distinct groups of buttons

406
00:18:32,870 --> 00:18:35,130
and to make our code more readable.

407
00:18:35,130 --> 00:18:36,720
And I've also included a comment to show

408
00:18:36,720 --> 00:18:39,360
the differences between the two sets.

409
00:18:39,360 --> 00:18:41,250
Now, the first group of buttons are used

410
00:18:41,250 --> 00:18:42,570
to enter the miracle values

411
00:18:42,570 --> 00:18:45,120
that we'll be performing our calculations with.

412
00:18:45,120 --> 00:18:47,500
The second group of operations that we can perform

413
00:18:47,500 --> 00:18:50,570
on those values, the add, subtraction, multiplication,

414
00:18:50,570 --> 00:18:52,240
and so forth.

415
00:18:52,240 --> 00:18:54,730
Now, Kotlin can't work out the widgets' type

416
00:18:54,730 --> 00:18:56,920
from the call to findViewById,

417
00:18:56,920 --> 00:18:58,720
that just returns a view object,

418
00:18:58,720 --> 00:19:00,900
which could represent any type of object.

419
00:19:00,900 --> 00:19:03,530
So we need to provide Kotlin with a clue

420
00:19:03,530 --> 00:19:06,060
to the type of widget that we're expecting.

421
00:19:06,060 --> 00:19:07,300
Now I've done this in two ways,

422
00:19:07,300 --> 00:19:08,690
in the first group of buttons,

423
00:19:08,690 --> 00:19:11,780
I've done that by specifying the type of each widget

424
00:19:11,780 --> 00:19:14,940
that's the colon button that's part of the declaration,

425
00:19:14,940 --> 00:19:17,050
but another way to achieve the same thing

426
00:19:17,050 --> 00:19:20,003
is to specify the generic type that findViewById

427
00:19:21,280 --> 00:19:22,930
will actually return.

428
00:19:22,930 --> 00:19:25,700
And to do that, we specify in the type parameter

429
00:19:25,700 --> 00:19:28,803
in angle brackets, as you can see here on line 40.

430
00:19:28,803 --> 00:19:31,630
Now, you wouldn't normally mix the two ways of doing this,

431
00:19:31,630 --> 00:19:33,370
and you certainly shouldn't mix them

432
00:19:33,370 --> 00:19:34,760
in the same function,

433
00:19:34,760 --> 00:19:37,100
but I've done it here to show both ways,

434
00:19:37,100 --> 00:19:39,430
there's no advantage to either so pick one you like

435
00:19:39,430 --> 00:19:41,610
and stick with it and be consistent.

436
00:19:41,610 --> 00:19:43,180
Now obviously if you work for a company

437
00:19:43,180 --> 00:19:46,020
that has a style guide, and they specify

438
00:19:46,020 --> 00:19:48,620
one method or the other, then you'd use the approach

439
00:19:48,620 --> 00:19:50,960
that they are suggesting in their style guide.

440
00:19:50,960 --> 00:19:53,060
I would normally suggest using Google's style guide

441
00:19:53,060 --> 00:19:55,520
as a pointer, but as I've pointed out,

442
00:19:55,520 --> 00:19:57,150
they haven't produced one yet.

443
00:19:57,150 --> 00:19:58,800
All right, so at this point we now need to

444
00:19:58,800 --> 00:20:01,370
set a listener on the buttons so that they'll

445
00:20:01,370 --> 00:20:03,130
do something when they're tapped.

446
00:20:03,130 --> 00:20:05,030
Now, in the button click counter app

447
00:20:05,030 --> 00:20:06,870
there was only one button, so we used

448
00:20:06,870 --> 00:20:10,360
an anonymous in a class to set its listener.

449
00:20:10,360 --> 00:20:12,580
But here we're going to assign the same listener

450
00:20:12,580 --> 00:20:14,580
to multiple buttons, so we're gonna give

451
00:20:14,580 --> 00:20:16,930
the listener a name for that reason.

452
00:20:16,930 --> 00:20:19,486
Gonna come down here and code that in the

453
00:20:19,486 --> 00:20:21,495
OnCreate function.

454
00:20:21,495 --> 00:20:26,288
We're gonna type val listener is equal to

455
00:20:26,288 --> 00:20:31,288
View.OnClickListener, then in the

456
00:20:32,180 --> 00:20:34,580
left and right curly braces, we're going to type

457
00:20:34,580 --> 00:20:37,890
v then a dash and a greater than sign,

458
00:20:37,890 --> 00:20:42,367
press enter and type val b = v as Button,

459
00:20:44,220 --> 00:20:45,640
with a capital B.

460
00:20:45,640 --> 00:20:47,817
Then it's gonna be newNumber, the next line,

461
00:20:47,817 --> 00:20:52,817
newNumber.append (b.text).

462
00:20:54,910 --> 00:20:56,400
Okay, so what've I done there?

463
00:20:56,400 --> 00:20:58,980
Well, the variable listener holds a reference

464
00:20:58,980 --> 00:21:01,630
to a new OnClickListener instance,

465
00:21:01,630 --> 00:21:04,670
and its OnClick method just reads the caption

466
00:21:04,670 --> 00:21:07,260
of the button using the Text property,

467
00:21:07,260 --> 00:21:09,890
then appends it to any text already in

468
00:21:09,890 --> 00:21:12,550
the newNumber EditText widget.

469
00:21:12,550 --> 00:21:14,750
Now, when a button's tapped, and the

470
00:21:14,750 --> 00:21:17,160
Android Framework calls the onClick method,

471
00:21:17,160 --> 00:21:20,560
it passes in a reference to the button that was tapped.

472
00:21:20,560 --> 00:21:22,810
Now remember that all widgets are views,

473
00:21:22,810 --> 00:21:24,900
so any widget that's tapped can be passed

474
00:21:24,900 --> 00:21:28,250
as a parameter to onClick as an instance

475
00:21:28,250 --> 00:21:30,810
of its base class view.

476
00:21:30,810 --> 00:21:32,860
Now, not all views can have text,

477
00:21:32,860 --> 00:21:35,325
so before we refer to the Text property,

478
00:21:35,325 --> 00:21:39,140
we have to actually cast B as a widget that does

479
00:21:39,140 --> 00:21:40,900
have a text property.

480
00:21:40,900 --> 00:21:43,530
In this case, that's a button because we know

481
00:21:43,530 --> 00:21:46,110
we're attaching this listener to buttons.

482
00:21:46,110 --> 00:21:48,920
Now, B isn't a very good name for a variable,

483
00:21:48,920 --> 00:21:51,290
but in a short function like this, two lines,

484
00:21:51,290 --> 00:21:52,640
it's not worth spending any time

485
00:21:52,640 --> 00:21:54,840
to come up with anything more meaningful.

486
00:21:54,840 --> 00:21:56,500
Definitely don't use names like that

487
00:21:56,500 --> 00:21:58,700
for variables that have a wider scope,

488
00:21:58,700 --> 00:22:00,640
or that exist in more complex functions

489
00:22:00,640 --> 00:22:02,570
with many lines of code.

490
00:22:02,570 --> 00:22:04,190
All right, so the next step is to assign

491
00:22:04,190 --> 00:22:06,830
this listener to each of the 11 buttons,

492
00:22:06,830 --> 00:22:09,000
from zero to nine and the decimal point,

493
00:22:09,000 --> 00:22:11,660
so that it's called when one of them's clicked.

494
00:22:11,660 --> 00:22:14,223
So to do that, we need to, on the line below,

495
00:22:15,082 --> 00:22:17,641
for each one, button, whatever the button is,

496
00:22:17,641 --> 00:22:21,483
button0.setOnClickListener and we're going

497
00:22:21,483 --> 00:22:23,563
to type in listener as the argument,

498
00:22:24,887 --> 00:22:26,180
and we'll do the same for the other buttons,

499
00:22:26,180 --> 00:22:27,480
so we've got buttons one through nine

500
00:22:27,480 --> 00:22:28,730
and then also we've got

501
00:22:32,620 --> 00:22:37,620
Dot, then we've got nine, eight, seven, six, five,

502
00:22:38,819 --> 00:22:42,380
four, three, two, one and obviously button zero was

503
00:22:42,380 --> 00:22:43,730
the first one that was set.

504
00:22:45,380 --> 00:22:47,330
Now I guess if you wanted to be clever,

505
00:22:47,330 --> 00:22:49,320
we could have stored all the button variables

506
00:22:49,320 --> 00:22:50,820
in an array and looped through it

507
00:22:50,820 --> 00:22:53,460
to set the listener instead of copying each line

508
00:22:53,460 --> 00:22:54,470
like I've done.

509
00:22:54,470 --> 00:22:56,440
But with only 11 buttons, it probably wouldn't save

510
00:22:56,440 --> 00:22:58,740
any lines of code, but if I was implementing

511
00:22:58,740 --> 00:23:00,760
a full keyboard, then I'd certainly look

512
00:23:00,760 --> 00:23:02,210
at doing something like that.

513
00:23:03,380 --> 00:23:05,240
Now, we should now be able to run the programme

514
00:23:05,240 --> 00:23:06,890
on an emulator and make sure the buttons

515
00:23:06,890 --> 00:23:08,090
work as they should.

516
00:23:08,090 --> 00:23:09,940
But this video is getting a bit long,

517
00:23:09,940 --> 00:23:11,380
so let's actually look at doing that

518
00:23:11,380 --> 00:23:12,323
in the next video.

