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.