1
00:00:03,890 --> 00:00:05,759
Alright so we're going to talk about

2
00:00:05,759 --> 00:00:08,250
singleton classes, and specifically the

3
00:00:08,250 --> 00:00:10,980
AppDatabase class. So our AppDatabase

4
00:00:10,980 --> 00:00:13,019
class should work and we'll be able to

5
00:00:13,019 --> 00:00:15,660
test it soon. Before that though there's

6
00:00:15,660 --> 00:00:17,760
a change I want to make - I want to make

7
00:00:17,760 --> 00:00:20,970
it a singleton. Now a singleton class is

8
00:00:20,970 --> 00:00:23,310
one that only allows a single instance

9
00:00:23,310 --> 00:00:26,369
to be created. We've used a few singletons

10
00:00:26,369 --> 00:00:28,830
so far - the most recent is the Content

11
00:00:28,830 --> 00:00:31,289
Resolver. There's only a single Content

12
00:00:31,289 --> 00:00:33,270
Resolver instance, although it's hard to

13
00:00:33,270 --> 00:00:35,489
check that from the source code because

14
00:00:35,489 --> 00:00:37,050
Content Resolver's an abstract class,

15
00:00:37,050 --> 00:00:39,480
and the implementation's provided by

16
00:00:39,480 --> 00:00:42,210
Android. Now we also created a singleton -

17
00:00:42,210 --> 00:00:45,899
our Tasks Contract object. In Kotlin,

18
00:00:45,899 --> 00:00:48,300
object is automatically a thread

19
00:00:48,300 --> 00:00:51,149
safe singleton. Unfortunately though, we

20
00:00:51,149 --> 00:00:52,860
can't make our AppDatabase class an

21
00:00:52,860 --> 00:00:55,379
object, and that's because we can't pass

22
00:00:55,379 --> 00:00:58,109
arguments to an object constructor. The

23
00:00:58,109 --> 00:00:59,789
reason for that is because objects don't

24
00:00:59,789 --> 00:01:02,309
actually have a constructor. We can use

25
00:01:02,309 --> 00:01:04,860
an object in our class to return a

26
00:01:04,860 --> 00:01:07,500
single instance of it. There's two stages

27
00:01:07,500 --> 00:01:10,439
to making a class into a singleton. The

28
00:01:10,439 --> 00:01:13,170
first step's easy - we mark the constructor

29
00:01:13,170 --> 00:01:15,570
as private so that nothing else can

30
00:01:15,570 --> 00:01:18,299
instantiate our class. So let's go ahead

31
00:01:18,299 --> 00:01:22,020
and do that now. So we've got - up here

32
00:01:22,020 --> 00:01:24,180
in our definition - internal class App

33
00:01:24,180 --> 00:01:26,580
Database constructor. We're going to put

34
00:01:26,580 --> 00:01:29,180
the private key word before constructor,

35
00:01:29,180 --> 00:01:32,490
so we're now marking that as private. So

36
00:01:32,490 --> 00:01:34,229
now the only thing that can create an

37
00:01:34,229 --> 00:01:36,450
instance of AppDatabase is AppData

38
00:01:36,450 --> 00:01:39,299
base itself, either via its own functions,

39
00:01:39,299 --> 00:01:41,880
or functions in an inner class or

40
00:01:41,880 --> 00:01:44,670
companion object. Now the reason I've

41
00:01:44,670 --> 00:01:46,860
done that is because we only want a

42
00:01:46,860 --> 00:01:48,869
single instance of this class to exist.

43
00:01:48,869 --> 00:01:51,750
As well as creating our database, this

44
00:01:51,750 --> 00:01:54,000
class also provides the connection to

45
00:01:54,000 --> 00:01:55,200
the database.

46
00:01:55,200 --> 00:01:57,659
Sqlite can support multiple users

47
00:01:57,659 --> 00:02:00,180
but it locks the entire database when

48
00:02:00,180 --> 00:02:02,670
writing to it. Our app is a single user,

49
00:02:02,670 --> 00:02:04,979
but if we allowed many instances of this

50
00:02:04,979 --> 00:02:07,890
AppDatabase class to be created, then

51
00:02:07,890 --> 00:02:09,899
each one would, effectively, be a

52
00:02:09,899 --> 00:02:12,330
different sqlite user, with its own

53
00:02:12,330 --> 00:02:13,230
connection to the

54
00:02:13,230 --> 00:02:15,390
database. Now that's not the end of the

55
00:02:15,390 --> 00:02:17,370
world, and the app would probably

56
00:02:17,370 --> 00:02:19,650
function just fine most of the time, as

57
00:02:19,650 --> 00:02:22,500
long as several instances didn't all try

58
00:02:22,500 --> 00:02:24,720
to execute the code to create the

59
00:02:24,720 --> 00:02:27,440
database tables simultaneously, of course.

60
00:02:27,440 --> 00:02:30,180
Now obviously, if you allow instances

61
00:02:30,180 --> 00:02:32,640
of a class to be created at will, then

62
00:02:32,640 --> 00:02:34,349
there's no way to guarantee that there's

63
00:02:34,349 --> 00:02:36,720
only one instance. So making the

64
00:02:36,720 --> 00:02:39,120
constructor private is the first step in

65
00:02:39,120 --> 00:02:42,450
creating a singleton class. Now equally,

66
00:02:42,450 --> 00:02:44,940
obviously, if there's no way to create

67
00:02:44,940 --> 00:02:47,160
any instances of a class, then it's not going

68
00:02:47,160 --> 00:02:49,440
to be much use to anyone unless all its

69
00:02:49,440 --> 00:02:51,720
fields and methods are available without

70
00:02:51,720 --> 00:02:53,910
creating an instance, as we saw with our

71
00:02:53,910 --> 00:02:57,599
columns object in the Tasks Contract. So

72
00:02:57,599 --> 00:02:59,220
how do we allow that single instance to

73
00:02:59,220 --> 00:03:01,799
be created. Well you'll find many

74
00:03:01,799 --> 00:03:03,810
examples of how to create Singleton's on

75
00:03:03,810 --> 00:03:06,709
the internet. They're mainly in Java, and

76
00:03:06,709 --> 00:03:09,290
unfortunately many of them are flawed.

77
00:03:09,290 --> 00:03:12,480
Android is a multi-threaded framework

78
00:03:12,480 --> 00:03:15,299
and class instances can be created on

79
00:03:15,299 --> 00:03:18,299
more than one thread. Any attempt to

80
00:03:18,299 --> 00:03:20,849
implement a singleton, has to cater for

81
00:03:20,849 --> 00:03:23,250
the same objects being created at the

82
00:03:23,250 --> 00:03:26,819
same time, from different threads. In Java,

83
00:03:26,819 --> 00:03:29,160
one solution is to use a static inner

84
00:03:29,160 --> 00:03:31,530
class which has a method returning an

85
00:03:31,530 --> 00:03:34,049
instance of the singleton class. Now the

86
00:03:34,049 --> 00:03:36,060
obvious solution of checking if the

87
00:03:36,060 --> 00:03:38,099
instance is null, than creating a new

88
00:03:38,099 --> 00:03:40,560
instance only if it is, doesn't work if

89
00:03:40,560 --> 00:03:43,079
another thread calls the method before

90
00:03:43,079 --> 00:03:46,230
the first call has created the object. So

91
00:03:46,230 --> 00:03:47,819
that method has to cope with being

92
00:03:47,819 --> 00:03:50,040
called from multiple threads at the same

93
00:03:50,040 --> 00:03:53,040
time, and a common solution is the double

94
00:03:53,040 --> 00:03:55,590
checked locking algorithm. So that

95
00:03:55,590 --> 00:03:57,720
basically does a null check twice, and

96
00:03:57,720 --> 00:04:00,720
locks the instance variable after the

97
00:04:00,720 --> 00:04:03,269
first check. Now there's a bit more to it

98
00:04:03,269 --> 00:04:05,329
than that, and as I've mentioned,

99
00:04:05,329 --> 00:04:07,739
multi-threaded programming is extremely

100
00:04:07,739 --> 00:04:10,440
difficult to get right. So let's have a

101
00:04:10,440 --> 00:04:12,629
look at how we might implement that in a

102
00:04:12,629 --> 00:04:14,790
companion object, and then I'll show you

103
00:04:14,790 --> 00:04:18,060
our reusable solution. So our companion

104
00:04:18,060 --> 00:04:20,130
object will have a getInstance function,

105
00:04:20,130 --> 00:04:23,430
to return an instance of AppDatabase. So

106
00:04:23,430 --> 00:04:24,570
I'm going to go ahead and add this at

107
00:04:24,570 --> 00:04:27,320
the end of the class.

108
00:04:27,320 --> 00:04:29,280
Alright so I'm going to come down here,

109
00:04:29,280 --> 00:04:30,600
right at the bottom of the class

110
00:04:30,600 --> 00:04:33,660
before the last right curly brace. We're

111
00:04:33,660 --> 00:04:36,000
going to type companion object and press

112
00:04:36,000 --> 00:04:38,220
ENTER there, and you can see that Android

113
00:04:38,220 --> 00:04:40,440
studio fills out the rest for us. Then

114
00:04:40,440 --> 00:04:46,220
I'm going to type private var instance

115
00:04:46,220 --> 00:04:50,840
colon AppDatabase question mark equals null.

116
00:04:50,840 --> 00:04:53,550
Then also what I'm going to do, is add

117
00:04:53,550 --> 00:04:58,620
the volatile annotation to that

118
00:04:58,620 --> 00:05:01,349
definition there, and then I'm going to create

119
00:05:01,349 --> 00:05:03,900
a function called getInstance, fun get

120
00:05:03,900 --> 00:05:07,410
Instance, and parentheses. We're going to

121
00:05:07,410 --> 00:05:12,360
pass a context, so context : Context, then

122
00:05:12,360 --> 00:05:14,729
outside of the parentheses : App

123
00:05:14,729 --> 00:05:18,449
Database is equal to. Then on the next line

124
00:05:18,449 --> 00:05:22,130
we're going to type instance question mark :

125
00:05:22,130 --> 00:05:27,030
synchronized, in a parentheses, this. Then

126
00:05:27,030 --> 00:05:29,250
left and right curly braces, and then

127
00:05:29,250 --> 00:05:30,479
we're going to type within that curly

128
00:05:30,479 --> 00:05:32,539
brace, within those curly braces, instance

129
00:05:32,539 --> 00:05:37,440
question mark : AppDatabase. Then in

130
00:05:37,440 --> 00:05:42,949
parentheses it's going to be context, and

131
00:05:42,949 --> 00:05:45,030
then outside of the right parentheses,

132
00:05:45,030 --> 00:05:47,580
dot also, and then we're going to

133
00:05:47,580 --> 00:05:49,080
introduce left and right curly braces

134
00:05:49,080 --> 00:05:53,750
again and type instance equals it.

135
00:05:53,750 --> 00:05:56,220
Alright, so what have we done here? Well

136
00:05:56,220 --> 00:05:59,009
we've used two Elvis operators which are

137
00:05:59,009 --> 00:06:02,550
our to two null checks. On the first line, we

138
00:06:02,550 --> 00:06:04,110
return instance if it isn't null,

139
00:06:04,110 --> 00:06:06,659
otherwise the synchronized block of code

140
00:06:06,659 --> 00:06:09,630
is executed. So that locks the variable

141
00:06:09,630 --> 00:06:11,729
to prevent access from another thread.

142
00:06:11,729 --> 00:06:14,130
Inside that block we once again return

143
00:06:14,130 --> 00:06:17,400
instance, if it now isn't null, so if

144
00:06:17,400 --> 00:06:19,169
another thread has managed to create it,

145
00:06:19,169 --> 00:06:22,380
in other words. But if it is null, we create

146
00:06:22,380 --> 00:06:24,720
a new AppDatabase instance and then

147
00:06:24,720 --> 00:06:28,380
return that. Now the also function calls

148
00:06:28,380 --> 00:06:30,810
the specified block, a simple assignment

149
00:06:30,810 --> 00:06:33,539
here, and returns it. We assign the new

150
00:06:33,539 --> 00:06:35,909
instance, represented by it, to our

151
00:06:35,909 --> 00:06:38,159
instance variable. Now whenever this

152
00:06:38,159 --> 00:06:39,870
function's called again,

153
00:06:39,870 --> 00:06:41,790
instance won't be null and will be

154
00:06:41,790 --> 00:06:44,460
immediately returned. Now don't worry too

155
00:06:44,460 --> 00:06:46,140
much about exactly how this code's

156
00:06:46,140 --> 00:06:48,440
working. As I've said a few times,

157
00:06:48,440 --> 00:06:50,610
multi-threaded programming is very

158
00:06:50,610 --> 00:06:52,740
difficult. Fortunately though, Android

159
00:06:52,740 --> 00:06:54,840
gives us things like async tasks and

160
00:06:54,840 --> 00:06:57,750
loaders to take care of a lot of

161
00:06:57,750 --> 00:06:59,970
the complexity. Most of the time it's not

162
00:06:59,970 --> 00:07:02,010
something we need to worry about. I mean

163
00:07:02,010 --> 00:07:03,090
do you really want to worry about

164
00:07:03,090 --> 00:07:05,040
synchronizing threads and using the

165
00:07:05,040 --> 00:07:07,350
volatile annotation? You can click to

166
00:07:07,350 --> 00:07:09,330
get a description of why that volatile

167
00:07:09,330 --> 00:07:11,490
annotation's there. It makes changes to

168
00:07:11,490 --> 00:07:13,920
instance immediately available to other

169
00:07:13,920 --> 00:07:15,840
threads, and is one of the many things that

170
00:07:15,840 --> 00:07:18,510
people get wrong. OK, so that code as

171
00:07:18,510 --> 00:07:21,090
we've written it will work, but frankly

172
00:07:21,090 --> 00:07:23,490
it's horrible. Having to modify it to

173
00:07:23,490 --> 00:07:26,250
create different singleton classes could

174
00:07:26,250 --> 00:07:28,470
be a good way to introduce bugs. What

175
00:07:28,470 --> 00:07:30,780
would be really useful is some class

176
00:07:30,780 --> 00:07:32,700
that we could use to do this all for us.

177
00:07:32,700 --> 00:07:35,160
Now the good news here is that such a

178
00:07:35,160 --> 00:07:38,250
class exists. There's a link to the

179
00:07:38,250 --> 00:07:40,440
article about it in the resources

180
00:07:40,440 --> 00:07:42,120
section for this video, and actually

181
00:07:42,120 --> 00:07:43,020
you'll see that in a moment.

182
00:07:43,020 --> 00:07:44,910
I'm not going to open the link in my

183
00:07:44,910 --> 00:07:46,950
browser though, and that's because the

184
00:07:46,950 --> 00:07:49,230
article isn't licensed for our

185
00:07:49,230 --> 00:07:51,300
commercial use so I can't really go

186
00:07:51,300 --> 00:07:53,370
through it all in this video. Now the

187
00:07:53,370 --> 00:07:54,600
article may not be available for

188
00:07:54,600 --> 00:07:56,190
commercial use, but we've had

189
00:07:56,190 --> 00:07:58,920
confirmation from Christophe Beyls, the

190
00:07:58,920 --> 00:08:02,040
author, that the code is. Now if you

191
00:08:02,040 --> 00:08:04,020
want to use his singleton class in your

192
00:08:04,020 --> 00:08:06,720
own code, that's fine. So what I'm going

193
00:08:06,720 --> 00:08:09,030
to do now is create a new Kotlin file

194
00:08:09,030 --> 00:08:14,130
class. I'll go ahead and do that, and I'm

195
00:08:14,130 --> 00:08:18,920
going to call this one SingletonHolder,

196
00:08:18,920 --> 00:08:22,140
and what I'm then going to do is paste

197
00:08:22,140 --> 00:08:25,170
in the code. And what I'm going to do is

198
00:08:25,170 --> 00:08:27,210
make sure that I delete these default

199
00:08:27,210 --> 00:08:29,070
comments, because I'm certainly not

200
00:08:29,070 --> 00:08:31,110
trying to claim any credit for this

201
00:08:31,110 --> 00:08:33,510
code. So I'm going to paste that in there now, and

202
00:08:33,510 --> 00:08:35,549
this is the code there from Christophe

203
00:08:35,549 --> 00:08:37,650
Beyls, as I said. So as you can see

204
00:08:37,650 --> 00:08:39,270
though, I have added a KDoc to show who

205
00:08:39,270 --> 00:08:41,940
wrote the code, and also the URL for the

206
00:08:41,940 --> 00:08:43,650
article. Have a read through the article,

207
00:08:43,650 --> 00:08:45,450
especially if you want to learn a bit

208
00:08:45,450 --> 00:08:48,960
more about how all this works. So the

209
00:08:48,960 --> 00:08:51,090
only change that I've made to Christophe's

210
00:08:51,090 --> 00:08:54,090
code is to add the usual logging, our

211
00:08:54,090 --> 00:08:56,160
usual logging. There's only, and that's

212
00:08:56,160 --> 00:08:57,600
only there really to make it easier to

213
00:08:57,600 --> 00:08:59,730
understand what happens when we run the

214
00:08:59,730 --> 00:09:01,590
app, and you'll probably want to delete

215
00:09:01,590 --> 00:09:03,930
the constant logging line if you use

216
00:09:03,930 --> 00:09:06,420
this class in your own apps. So this

217
00:09:06,420 --> 00:09:09,180
class is basically a generic

218
00:09:09,180 --> 00:09:11,610
version of the code I've just added to

219
00:09:11,610 --> 00:09:14,040
our AppDatabase class in the companion

220
00:09:14,040 --> 00:09:16,590
object. Alright. So what I'm going to do

221
00:09:16,590 --> 00:09:18,510
is go back to that code and comment out

222
00:09:18,510 --> 00:09:27,240
my companion object, and what we're going

223
00:09:27,240 --> 00:09:28,770
to do is use the singleton class

224
00:09:28,770 --> 00:09:31,170
instead. So what I'm going to do is, above

225
00:09:31,170 --> 00:09:32,910
that commented out code, I'm going to

226
00:09:32,910 --> 00:09:35,610
type companion object. Then what I'm

227
00:09:35,610 --> 00:09:38,490
going to do is delete the left and right

228
00:09:38,490 --> 00:09:40,020
clearly braces - we don't need them - and

229
00:09:40,020 --> 00:09:42,660
instead I'm going to put colon. I'm going to type

230
00:09:42,660 --> 00:09:46,440
singleton holder, then in a less than and

231
00:09:46,440 --> 00:09:47,580
greater than sign there I'm going to type

232
00:09:47,580 --> 00:09:53,250
AppDatabase comma context, and then I'm

233
00:09:53,250 --> 00:09:56,190
going to type parentheses two colons and

234
00:09:56,190 --> 00:10:00,600
AppDatabase. Now that's a lot easier. You

235
00:10:00,600 --> 00:10:02,760
can use it in any class - it has a

236
00:10:02,760 --> 00:10:05,130
single argument constructor just by

237
00:10:05,130 --> 00:10:07,590
changing the two occurrences of the

238
00:10:07,590 --> 00:10:09,930
class name. Now passing just one argument

239
00:10:09,930 --> 00:10:11,370
to the constructor is normally all

240
00:10:11,370 --> 00:10:13,260
you'll need. You'll often need to pass just

241
00:10:13,260 --> 00:10:15,680
a single argument, a context for example,

242
00:10:15,680 --> 00:10:18,420
to your singletons. Now I said

243
00:10:18,420 --> 00:10:20,700
that's normally all you'll need, but I don't

244
00:10:20,700 --> 00:10:21,810
want to imply that creating

245
00:10:21,810 --> 00:10:24,030
singletons is normal. They're not

246
00:10:24,030 --> 00:10:25,860
something you need to create very often,

247
00:10:25,860 --> 00:10:28,500
but when you do need to create them, you

248
00:10:28,500 --> 00:10:31,320
now have a way to do it right. Whenever

249
00:10:31,320 --> 00:10:32,940
another class needs an instance of this

250
00:10:32,940 --> 00:10:35,310
AppDatabase class, it calls the get

251
00:10:35,310 --> 00:10:37,350
Instance method. The first time that's

252
00:10:37,350 --> 00:10:37,800
called,

253
00:10:37,800 --> 00:10:40,260
instance will be null and a new instance

254
00:10:40,260 --> 00:10:41,820
of the AppDatabase class will be

255
00:10:41,820 --> 00:10:44,310
created. And every time it's called after

256
00:10:44,310 --> 00:10:46,440
that, the caller will get a reference to

257
00:10:46,440 --> 00:10:48,450
the single instance of the class that's

258
00:10:48,450 --> 00:10:50,940
stored in the instance field. Alright.

259
00:10:50,940 --> 00:10:52,890
So in the next video we're going to add

260
00:10:52,890 --> 00:10:55,140
some code to the onUpgrade function, and

261
00:10:55,140 --> 00:10:57,690
then run a very basic test of the App

262
00:10:57,690 --> 00:11:01,910
Database class. See you in the next video.

