1 00:00:05,470 --> 00:00:11,140 So we left the last video with an error in main activity when we tried to call the putExtra function, 2 00:00:11,500 --> 00:00:13,970 and you can see the error on line 50 on screen. 3 00:00:14,320 --> 00:00:20,050 Now I said that putExtra can be used to add more complex objects to the intent, but there is a condition 4 00:00:20,140 --> 00:00:25,180 that the object must meet for it all to work. Now that object has to be serializable. 5 00:00:25,180 --> 00:00:31,150 Now there's a good description of what that means in Oracle's Java documentation, but rather than 6 00:00:31,150 --> 00:00:35,520 going straight to the page I'm going to just search for it in Google. 7 00:00:39,500 --> 00:00:41,030 I'll do a search for Java 8 00:00:42,230 --> 00:00:43,010 serializable, 9 00:00:46,870 --> 00:00:51,840 and there's a likely looking link right at the top there, but the actual second one, 10 00:00:51,840 --> 00:00:57,590 Serializable objects the Java tutorials, is the one that promises to be the most informative. 11 00:01:00,580 --> 00:01:05,090 And in actual fact I'll just go back there because the description really has enough information on the 12 00:01:05,090 --> 00:01:11,060 screen there, "To serialize an object means to convert its state to a byte stream so that the byte stream can 13 00:01:11,060 --> 00:01:14,120 be reverted back into a copy of the object". 14 00:01:14,150 --> 00:01:20,750 So if an object is serializable it can be stored and retrieved. Now a byte stream can be saved to disk or 15 00:01:20,750 --> 00:01:22,000 held in memory. 16 00:01:22,010 --> 00:01:26,630 We don't know exactly what the putExtra method will do, but in this case it doesn't matter. 17 00:01:26,870 --> 00:01:33,380 Let's long as it can serialize our object, it can store it in the intent for the new activity to retrieve. 18 00:01:33,380 --> 00:01:38,410 Now go ahead and go back into that link again, because the full page may tell us how to make our photo 19 00:01:38,420 --> 00:01:41,690 objects serializable. So that's handy. 20 00:01:41,690 --> 00:01:48,860 The second sentence tells us that a Java object, up here, so a Java object is serializable if its 21 00:01:48,860 --> 00:01:56,630 class or any of its superclass implements either the java.io.Serializable interface or its subinterface. 22 00:01:57,080 --> 00:02:01,280 So basically all we have to do here is make our photo class implement that interface. 23 00:02:01,320 --> 00:02:04,160 So let's go back to Android Studio and do that. 24 00:02:04,280 --> 00:02:06,330 So we're going to go back to our photo object, 25 00:02:10,419 --> 00:02:16,780 sorry our photo class I should would say, and what we need to do is make this serializable, and to do that we just come down here. 26 00:02:16,780 --> 00:02:21,760 What I might do is make a bit more space, and on the end of that, 27 00:02:21,820 --> 00:02:26,410 after the closing parentheses, I'm going to put colon Serializable, 28 00:02:29,400 --> 00:02:32,350 and it's java dot io. Now in Java, 29 00:02:32,350 --> 00:02:33,740 that's all we must do, 30 00:02:33,940 --> 00:02:38,080 but there's one other thing that we should do, assuming that works of course. 31 00:02:38,080 --> 00:02:41,890 Things are changing all the time and a week after I first typed that code, 32 00:02:42,050 --> 00:02:47,080 Android Studio gives an error instead of importing java.io.Serializable. 33 00:02:47,150 --> 00:02:52,600 Now if it was just a case of typing the import in manually, I'd probably have stuck with using Serializable, 34 00:02:52,890 --> 00:02:58,770 but as well as causing that error, Jetbrains have added a really neat feature to the Kotlin plugin. Now 35 00:02:58,780 --> 00:03:03,180 Jetbrains, in case you didn't know, are the people who produced the Kotlin language. 36 00:03:03,220 --> 00:03:08,800 Now I've got a bit of a quandary now. Do I show you how to implement Serializable correctly, or do I show you 37 00:03:08,800 --> 00:03:10,390 that neat feature instead. 38 00:03:10,450 --> 00:03:12,730 So we've decided to do both. 39 00:03:12,910 --> 00:03:17,590 Now this isn't something that we'd normally do, but there's a lot of comments on the Internet about 40 00:03:17,590 --> 00:03:20,730 Serializable being slow on Android. 41 00:03:20,740 --> 00:03:22,000 Now that can be true. 42 00:03:22,150 --> 00:03:27,470 There's another interface that can perform a lot better than Serializable. That other interface 43 00:03:27,470 --> 00:03:30,950 is called parcelable, and we'll come to that next. 44 00:03:30,990 --> 00:03:36,840 Now the reason I'm going to show you both functions is because Serializable can also be faster than parcelable. 45 00:03:37,180 --> 00:03:42,810 It depends on the structure of the object being serialized, and it also depends on Serializable being 46 00:03:42,820 --> 00:03:46,320 implemented correctly, which often isn't done. Now 47 00:03:46,330 --> 00:03:48,610 Serializable is very easy to implement. 48 00:03:48,820 --> 00:03:54,180 As I said, all that's absolutely necessary is to add the implementation to the class declaration. 49 00:03:54,310 --> 00:03:57,790 So that's in Java, but in Kotlin that's no longer enough. 50 00:03:57,790 --> 00:04:01,440 Now Jetbrains are working on building Kotlin support for serialization, 51 00:04:01,510 --> 00:04:03,040 but that's not yet ready. 52 00:04:03,340 --> 00:04:07,650 So if you want to use it, we'll be using the Java serialization interface. 53 00:04:08,190 --> 00:04:13,650 Now to specify that, rather than the Kotlin interface, we just add the import manually. 54 00:04:14,030 --> 00:04:15,540 Now you can see in the case here, 55 00:04:15,730 --> 00:04:21,940 when I selected, or rather when I typed in serializable, I selected java dot io in the pop up, and you can 56 00:04:21,940 --> 00:04:27,580 see up here that under the import, we've got java.io.Serializable. 57 00:04:27,730 --> 00:04:34,330 So if you do get an error, that removes the error, and we can carry on creating our class. Now Java code can 58 00:04:34,330 --> 00:04:39,440 run on many different platforms, using different versions and types of the Java virtual machine 59 00:04:39,590 --> 00:04:47,520 or JVM. Google have written their own JVM, Dalvik, earlier versions of Android, and ART on the later versions. 60 00:04:47,530 --> 00:04:53,350 Now if you rely on the default implementation of Serializable, then the data might not be recoverable 61 00:04:53,440 --> 00:04:56,310 using a different virtual machine or version of Java. 62 00:04:56,570 --> 00:04:59,440 Now strictly speaking that's not going to be a problem here, 63 00:04:59,560 --> 00:05:05,050 and that's because our serialized photo objects will only be used within a single app while it's running. 64 00:05:05,680 --> 00:05:07,970 But it's always a good idea to do things properly. 65 00:05:08,050 --> 00:05:14,050 So you may for example, decide to provide a bookmark feature to allow users to store certain photo details 66 00:05:14,320 --> 00:05:15,480 in a favorites file, 67 00:05:15,790 --> 00:05:22,200 and if Google subsequently update the version of Java or the JVM, then your favorites may not de-serialize 68 00:05:22,210 --> 00:05:23,230 correctly. 69 00:05:23,640 --> 00:05:28,440 Now considering how easy it is to fix that issue, there's really no reason not to do that. 70 00:05:28,510 --> 00:05:34,810 So all we really have to do is add a serial version UID to the class. Now that needs to be a static field 71 00:05:34,810 --> 00:05:35,520 in Java, 72 00:05:35,710 --> 00:05:38,750 so that means we have to use a companion object in Kotlin. 73 00:05:39,070 --> 00:05:44,540 So I'm going to add that to the style of a class just after the definition, before the override to 74 00:05:44,620 --> 00:05:45,440 toString. 75 00:05:45,700 --> 00:05:51,200 So I'm going to type companion object, press enter there so it writes some of the code for us. 76 00:05:51,260 --> 00:05:54,610 We're going to type private const val, 77 00:05:57,970 --> 00:06:08,510 and it's going to be serial, spelling and case is very important here, serialVersionUID equals one L, 78 00:06:09,510 --> 00:06:11,490 so serialVersion 79 00:06:11,500 --> 00:06:18,880 UID. Now the version number's used by the serialization code, to check that the data it's retrieving 80 00:06:19,180 --> 00:06:22,170 is the same version as the data that was stored. 81 00:06:22,220 --> 00:06:28,030 Now if you don't create your own serial version UID, then Java generates one for you, and different 82 00:06:28,030 --> 00:06:31,400 versions of Java may generate different UIDs. 83 00:06:31,630 --> 00:06:34,600 And that's why you can get problems by not defining your own 84 00:06:34,620 --> 00:06:37,390 UID. Now because that's so easy, 85 00:06:37,390 --> 00:06:42,050 many programmers just implement Serializable like this and then complain that it's slow. 86 00:06:42,190 --> 00:06:44,300 Now with a simple class like this one, 87 00:06:44,380 --> 00:06:50,220 this basic implementation will work just fine for what we want to do with it, especially on modern devices. 88 00:06:50,560 --> 00:06:56,770 But the problem with performance arises, because the JVM has been given no indication of how to serialize 89 00:06:56,770 --> 00:07:00,970 our class, so it has to use something called reflection to work it all out. 90 00:07:01,270 --> 00:07:07,330 Now reflection involves examining the class at runtime, to work out the fields that need to be stored in the 91 00:07:07,330 --> 00:07:08,490 byte stream. 92 00:07:08,500 --> 00:07:13,440 Now we can do a lot better than that by implementing three additional functions. 93 00:07:13,600 --> 00:07:18,430 Now the details of these as are as described in the documentation for Java dot 94 00:07:18,520 --> 00:07:24,520 io dot Serializable, and the quickest way to get to that is just to control click on serialization in our class 95 00:07:24,520 --> 00:07:25,700 declaration. 96 00:07:25,810 --> 00:07:30,300 In the case of a Mac I'm just going to do a control click. 97 00:07:30,360 --> 00:07:38,930 Now I'm not going to go through this Java doc but if we scroll up into round about line 60, from memory, there's the 98 00:07:38,940 --> 00:07:41,020 three functions that we should implement. 99 00:07:41,220 --> 00:07:46,860 So I'm going to start with write object, which puts the value of our class properties onto the output stream 100 00:07:46,860 --> 00:07:48,490 that's used for serialization. 101 00:07:48,630 --> 00:07:54,690 So I'm going to close that down, and back in photo we're going to do that. So we're going to type in this 102 00:07:54,810 --> 00:07:58,120 after the toString function that we've written. 103 00:07:58,890 --> 00:08:02,830 So we're going to start with an annotation, at throws 104 00:08:02,910 --> 00:08:06,150 parentheses IOException 105 00:08:06,150 --> 00:08:14,670 colon colon class, then we're going to start with the definition which is going to be private fun write 106 00:08:14,670 --> 00:08:15,490 Object, 107 00:08:15,510 --> 00:08:19,860 that's that first one. Then it's going to be out colon Java dot 108 00:08:20,100 --> 00:08:23,460 io dot Object 109 00:08:23,490 --> 00:08:28,330 OutputStream. Then we'll start with a log, 110 00:08:28,440 --> 00:08:34,429 so Log.d parentheses tag, and this time we're just going to type photo because we haven't actually created a tag constant here, 111 00:08:34,710 --> 00:08:38,400 and do a writeObject called. 112 00:08:40,600 --> 00:08:47,040 Then we're going to do out dot writeUTF parentheses title. 113 00:08:47,110 --> 00:08:48,430 I'm just going to copy that, 114 00:08:48,520 --> 00:08:54,830 the remaining fields. We need to do author, author Id, link, tags and image. 115 00:08:54,970 --> 00:09:06,000 The next one is going to be author, author Id, then we want link, next we want tags, 116 00:09:06,650 --> 00:09:13,110 and finally we want image. So that's the Kotlin equivalent of a Java signature that the function 117 00:09:13,110 --> 00:09:16,390 must have. Now I've logged when it gets called, 118 00:09:16,700 --> 00:09:19,470 and then we just write each of our properties to the stream. 119 00:09:19,800 --> 00:09:25,380 Now the next one's a complementary function, to take data off the stream and set the values into our 120 00:09:25,380 --> 00:09:26,870 class properties. 121 00:09:26,880 --> 00:09:28,240 So let's go ahead and do that one. 122 00:09:28,380 --> 00:09:29,600 We'll start with an annotation again. 123 00:09:29,610 --> 00:09:40,590 So at Throws parentheses, it's going to be IOException colon colon class comma, then ClassNotFoundException 124 00:09:41,070 --> 00:09:46,840 colon colon class, then the actual function definition will be private 125 00:09:47,040 --> 00:09:52,710 fun readObject parentheses inStream 126 00:09:52,850 --> 00:09:57,130 colon. Then it's going to be java dot. 127 00:09:57,150 --> 00:10:00,060 io dot ObjectOutputStream, 128 00:10:03,120 --> 00:10:07,480 and the code, we're going to do a Log.d Photo again 129 00:10:07,680 --> 00:10:09,320 comma 130 00:10:09,480 --> 00:10:17,220 readObject called, and the code's going to be title equals inStream 131 00:10:17,480 --> 00:10:19,990 dot readUTF. 132 00:10:23,240 --> 00:10:26,660 I think that should be object dot inputStream, let's try that. 133 00:10:30,020 --> 00:10:32,310 I'll just stick the last one there. 134 00:10:34,350 --> 00:10:42,590 OK author is equal to inStream dot readUTF, 135 00:10:45,520 --> 00:11:02,580 then we've got author Id equals inStream dot readUTF, link equals inStream dot readUTF, two more, we've got tags equals in 136 00:11:02,800 --> 00:11:05,850 Stream dot readUTF, 137 00:11:06,210 --> 00:11:07,490 and the last one is image, 138 00:11:07,570 --> 00:11:10,400 so image equals inStream dot 139 00:11:10,420 --> 00:11:13,030 readUTF. 140 00:11:13,030 --> 00:11:14,830 Now we've got an error on each line, 141 00:11:14,830 --> 00:11:19,900 when we try to assign the value from the stream to our properties, and that's because all the properties 142 00:11:19,900 --> 00:11:22,670 were declared as foul so we can't change them. 143 00:11:22,960 --> 00:11:28,380 So to fix that, we just have to declare them as var in our primary constructor, or in the primary constructor. 144 00:11:28,750 --> 00:11:29,740 So let's go back and do that, 145 00:11:29,750 --> 00:11:39,150 so we're going to do that to all of them. So var, var, var, var, var, and the 146 00:11:42,620 --> 00:11:47,240 last one image, var, and you can see that fixes the errors. 147 00:11:47,810 --> 00:11:52,750 OK now the last function that we now have to implement is the read object, 148 00:11:52,750 --> 00:11:53,840 no data. 149 00:11:54,130 --> 00:11:55,540 So let's go and write that one now. 150 00:11:55,570 --> 00:12:12,430 So it's going to be at Throws parentheses ObjectStreamException colon colon class, and the function 151 00:12:12,430 --> 00:12:15,700 definition's private fun readObject 152 00:12:15,700 --> 00:12:21,870 NoData parentheses, and it's going to be just a Log.d 153 00:12:22,360 --> 00:12:31,930 Photo comma readObjectNoData called. 154 00:12:31,940 --> 00:12:33,900 Now don't worry too much about this function. 155 00:12:34,090 --> 00:12:40,810 It's intended for rare cases when you've created a subclass of the class that was originally serialized. 156 00:12:40,810 --> 00:12:42,780 Now we're not doing anything in this function. 157 00:12:42,790 --> 00:12:47,320 I've included it so you can see the Kotlin signature for all three functions. 158 00:12:47,560 --> 00:12:53,320 So when we provide these three functions, the JVM no longer has to try to work out what goes where, when 159 00:12:53,320 --> 00:12:56,090 serializing or de-serializing the data. 160 00:12:56,320 --> 00:12:59,170 So this makes the process far more efficient. 161 00:12:59,240 --> 00:13:02,860 Alright so at this point we should find that the error's now fixed back in main activity. 162 00:13:02,860 --> 00:13:07,850 Let's go back and check that out, and we can see the intent dot putExtra has no longer got any errors. 163 00:13:07,850 --> 00:13:14,740 Now in my main activity's on item long click, we're using the putExtra function to store a photo object in the 164 00:13:14,740 --> 00:13:15,590 intent. 165 00:13:15,610 --> 00:13:20,470 Now the key we use comes from the photo transfer constant defined in the base class, and we talked about 166 00:13:20,470 --> 00:13:22,090 that before. 167 00:13:22,120 --> 00:13:27,850 Now we get the photo details by using the get photo function of the adapter, and telling it the position of the 168 00:13:27,890 --> 00:13:33,840 photo we want. And we have to start the activity which we do by calling start activity, and 169 00:13:33,840 --> 00:13:36,500 you can see that happening on line 51. 170 00:13:36,640 --> 00:13:42,730 Now what we haven't done yet is written the code to download and display the full size photo, but we 171 00:13:42,730 --> 00:13:46,900 can run the app to make sure that what we've done works so far, and that there's no errors. 172 00:13:46,900 --> 00:13:47,930 So let's go ahead and do that. 173 00:14:01,250 --> 00:14:07,430 The list can be scrolled as it could be before. When I tap on an item, we can see the Toast message 174 00:14:07,430 --> 00:14:09,710 should still appear, which it is 175 00:14:09,890 --> 00:14:13,300 as you can see there, so we haven't broken anything so far. 176 00:14:13,460 --> 00:14:20,600 So I'm going to try a long press now, and let's do that, and you can see that at this point, there's our 177 00:14:20,600 --> 00:14:22,730 photo details activity launched. 178 00:14:22,860 --> 00:14:25,180 Now it's just showing the placeholder at the moment, 179 00:14:25,280 --> 00:14:27,800 but we have got it launching successfully. 180 00:14:27,830 --> 00:14:33,350 Now we've also got the home button in the toolbar as well, so that bit's also working fine. 181 00:14:33,350 --> 00:14:38,510 Now the button doesn't work though, if you try clicking it. Clicking it should take us back to main activity but 182 00:14:38,510 --> 00:14:39,980 that's not working. 183 00:14:39,980 --> 00:14:43,110 The back button down here though, does work, 184 00:14:43,400 --> 00:14:45,640 but again you saw that the home button doesn't. 185 00:14:45,950 --> 00:14:50,840 Now the reason that the home button's not working, is that we didn't use the hierarchical parent option 186 00:14:51,200 --> 00:14:56,930 when we created the activity from the wizard. So we ticked it for search activity, but not for photo details 187 00:14:56,930 --> 00:14:57,920 activity. 188 00:14:57,980 --> 00:15:03,350 So let's have a look at what it did, when we ticked that option and chose main activity as the parent for 189 00:15:03,350 --> 00:15:04,730 search activity. 190 00:15:04,730 --> 00:15:06,110 So we're going to open up the manifest. I'm going to 191 00:15:09,560 --> 00:15:16,120 close down the log cat for now. We can actually see the differences between the two, between the two activities, 192 00:15:16,120 --> 00:15:23,130 the search activity and photo details activity. Search activity's got an extra attribute in its tag, and also 193 00:15:23,310 --> 00:15:25,630 a meta data tag. 194 00:15:25,620 --> 00:15:31,080 Now these tell the Android framework that search activity's parent is main activity, so it knows where 195 00:15:31,080 --> 00:15:34,410 to go back to when the home button's tapped. 196 00:15:34,410 --> 00:15:37,660 Now that's all that ticking the option in the wizard actually did, 197 00:15:38,090 --> 00:15:41,330 but if you forget then, then it's very easy to do it manually afterwards. 198 00:15:41,360 --> 00:15:46,610 So I'm going to go ahead and add the parent activity name attribute to the activity tag and copy the meta 199 00:15:46,620 --> 00:15:47,220 data. 200 00:15:47,280 --> 00:15:48,380 So I'm going to start over here. 201 00:15:48,390 --> 00:15:51,750 I'm in the search activity. So I'm going to copy this line here, 202 00:15:51,750 --> 00:15:57,440 this android parentActivityName equals MainActivity. 203 00:15:57,900 --> 00:16:01,390 Copy that, I'm going to come down here and put that into photo details, 204 00:16:01,580 --> 00:16:05,740 and I'm going to put it right at the end here, 205 00:16:06,600 --> 00:16:12,600 after photo details, after the label in the same place as it is, currently in the search activity. 206 00:16:13,110 --> 00:16:18,240 Now the other thing we need to do is copy this meta data, so let's go ahead and do that as well. 207 00:16:18,270 --> 00:16:25,970 So I'm going to copy that, and put that below down here, after the NoActionBar line. 208 00:16:26,580 --> 00:16:27,780 So if we run the app again now, 209 00:16:32,090 --> 00:16:34,300 and we'll just test that the home button now works. 210 00:16:38,420 --> 00:16:47,550 So I'm going to do a long tap and click on the home button, and now it goes back to main activity correctly, so that's working 211 00:16:47,550 --> 00:16:48,450 well. 212 00:16:48,500 --> 00:16:49,910 Alright so let's finish the video here. 213 00:16:49,920 --> 00:16:52,370 We've still got a bit of work to do. In the next one, 214 00:16:52,380 --> 00:16:57,400 we'll start talking about how to get the photo details activity to display the photo. 215 00:16:57,600 --> 00:16:58,970 So I'll see you in the next video.