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.

