Видео. Google I/O '17 Architecture Components - Introduction. Перевод субтитров.

Перевод английских субтитров на русские из видео Architecture Components - Introduction (Google I/O ‘17). Предпринят только для практики перевода с английского, скажем так to improve my reading and listening skills. Делается постепенно. Начало 20.08.2017, конец - 31.08.2017. All rights reserved.

Смотри другие переводы видео (субтитры) по этой теме: Tag: Architecture Components

Мой клон с русскими субтитрами:

Оригинальное видео:

Аннотация к видео:

  • Writing robust Android apps can be challenging, between complex lifecycle issues, unreliable mobile networks, and constrained device capabilities. Mistakes in these areas lead to memory leaks, crashing apps, drained batteries, and unhappy users. This session will cover a new approach to good Android app architecture, including an overview of functionality that will make these problems fundamentally easier to solve. This session is the first of three on this new initiative; be sure to check out the other two “Architecture Components” sessions.

Перевод:

  • Написание надежных приложений для Android может оказаться сложной задачей среди нетривиальных проблем регулирования жизненного цикла компонентов, ненадежных мобильных сетей и ограниченной производительности устройств. Ошибки в этих областях приводят к утечкам памяти, падениям приложений, неэффективному расходу батареи и, в итоге, к несчастным пользователям. Эта сессия будет посвящена новому подходу к хорошей архитектуре приложений для Android. В ней представлен обзор функциональности, которая позволит принципиально упростить решение данных проблем. Эта сессия является первой из трёх посвященных архитектурным компонентам. Обязательно посмотрите две другие.

Некоторые ссылки для понимая того, о чем говорится в докладе:

Перевод субтитров
English Русский
1
00:00:00,000 --> 00:00:05,189
[MUSIC PLAYING]

2
00:00:05,189 --> 00:00:05,980
MIKE CLERON: So hi.

3
00:00:05,980 --> 00:00:07,080
I'm Mike Cleron.

4
00:00:07,080 --> 00:00:08,650
I'm on the Android team.

5
00:00:08,650 --> 00:00:14,120
I manage the system UI framework
and UI toolkit teams there.

6
00:00:14,120 --> 00:00:17,650
We're going to be talking
today in a lot of detail

7
00:00:17,650 --> 00:00:21,790
about some big changes to
how we recommend that you

8
00:00:21,790 --> 00:00:23,710
build Android applications.

9
00:00:23,710 --> 00:00:26,110
But before we go into
a lot of the details,

10
00:00:26,110 --> 00:00:28,510
I thought would be helpful
to step back a bit,

11
00:00:28,510 --> 00:00:31,960
and frame the discussion by
talking about where we came

12
00:00:31,960 --> 00:00:34,730
from, and where we're going.

13
00:00:34,730 --> 00:00:36,100
So let's do that.

14
00:00:36,100 --> 00:00:39,010
So to start, Android
has always been based

15
00:00:39,010 --> 00:00:41,230
on some strong principles.

16
00:00:41,230 --> 00:00:43,330
Not surprisingly, those
were best expressed

17
00:00:43,330 --> 00:00:44,860
by Dianne Hackborn.

18
00:00:44,860 --> 00:00:46,600
She's the one who
actually architected

19
00:00:46,600 --> 00:00:48,880
most of the Android framework.

20
00:00:48,880 --> 00:00:51,160
She wrote a post about
this a few months back,

21
00:00:51,160 --> 00:00:54,310
and I have some
excerpts from that here.

22
00:00:54,310 --> 00:00:56,230
If you look at our
core primitives--

23
00:00:56,230 --> 00:01:00,100
activity, broadcast receiver,
service content provider,

24
00:01:00,100 --> 00:01:03,880
you might reasonably think that
those constitute an application

25
00:01:03,880 --> 00:01:05,012
framework.

26
00:01:05,012 --> 00:01:06,970
But that's not the right
way to think about it.

27
00:01:06,970 --> 00:01:10,120
These classes are
actually contracts

28
00:01:10,120 --> 00:01:14,910
between the application
and the operating system.

29
00:01:14,910 --> 00:01:16,950
They represent the minimal
amount of information

30
00:01:16,950 --> 00:01:20,790
necessary so that the OS knows
what's going on inside your app

31
00:01:20,790 --> 00:01:23,220
so we can manage it properly.


32
00:01:23,220 --> 00:01:27,060
So as an example, if your app
is running in the background,

33
00:01:27,060 --> 00:01:29,600
but is also exposing data
to another application

34
00:01:29,600 --> 00:01:32,492
through a content provider,
the OS needs to know that.

35
00:01:32,492 --> 00:01:34,950
And we need to know that so we
don't accidentally kill you.

36
00:01:34,950 --> 00:01:37,500
The content provider is a
mechanism that tells us that

37
00:01:37,500 --> 00:01:39,990
so that we can keep you alive.

38
00:01:39,990 --> 00:01:41,970
So we think of
these core classes

39
00:01:41,970 --> 00:01:44,790
as really being like the
fundamental laws of physics

40
00:01:44,790 --> 00:01:47,520
for Android, hence
the illustration.

41
00:01:47,520 --> 00:01:49,920
That is the cover
of the manuscript

42
00:01:49,920 --> 00:01:52,170
where Isaac Newton
first presented

43
00:01:52,170 --> 00:01:53,430
the basic laws of motion.

44
00:01:53,430 --> 00:01:56,620


45
00:01:56,620 --> 00:01:59,580
Now, fundamental laws
are a good thing.

46
00:01:59,580 --> 00:02:01,560
I use a shorthand when
talking about this.

47
00:02:01,560 --> 00:02:04,530
I say, Android has good bones,
even though people look at me

48
00:02:04,530 --> 00:02:06,780
funny after I say that.

49
00:02:06,780 --> 00:02:09,960
But what I mean by
that is that Android

50
00:02:09,960 --> 00:02:13,650
is based on a small,
stable, cohesive set

51
00:02:13,650 --> 00:02:15,150
of core primitives.

52
00:02:15,150 --> 00:02:18,390
And that allows a
common programming model

53
00:02:18,390 --> 00:02:20,940
across a really
incredibly diverse range

54
00:02:20,940 --> 00:02:24,750
of devices from wearables
to phones to tablets

55
00:02:24,750 --> 00:02:27,870
to TVs to cars, and more.

56
00:02:27,870 --> 00:02:30,210
This model also gives
application developers

57
00:02:30,210 --> 00:02:32,310
the freedom to choose
whatever framework

58
00:02:32,310 --> 00:02:34,170
they want inside
their application

59
00:02:34,170 --> 00:02:36,010
for their internal framework.

60
00:02:36,010 --> 00:02:38,070
So that means that we
on the Android team

61
00:02:38,070 --> 00:02:41,250
don't have to get involved
in debates about whether MVC

62
00:02:41,250 --> 00:02:45,540
is better than MVP, or whether
MVP is better than [? MVVBM. ?]

63
00:02:45,540 --> 00:02:49,260
You guys can pick whatever
makes sense to you.

64
00:02:49,260 --> 00:02:52,680
Now, that's a pretty good story
if you are in the operating

65
00:02:52,680 --> 00:02:55,921
system business like, say, me.

66
00:02:55,921 --> 00:02:57,420
But if you're in
the app development

67
00:02:57,420 --> 00:03:01,110
business like, say,
all of you, that's

68
00:03:01,110 --> 00:03:03,120
really only chapter
one of the story.

69
00:03:03,120 --> 00:03:04,890
And the reason for
that is because

70
00:03:04,890 --> 00:03:08,190
while strong fundamentals
and freedom of choice

71
00:03:08,190 --> 00:03:12,000
are good things, we know that
in your day to day jobs--

72
00:03:12,000 --> 00:03:16,730
and we know this because you
told us, you want more from us.

73
00:03:16,730 --> 00:03:19,690
So I'm going to abuse
my analogy a bit here.

74
00:03:19,690 --> 00:03:22,810
We can all appreciate the
simple elegance of Newton's laws

75
00:03:22,810 --> 00:03:27,725
of motion, but if your job
is to land a Rover on Mars,

76
00:03:27,725 --> 00:03:29,350
you don't want to
come to work each day

77
00:03:29,350 --> 00:03:31,810
and start with only F equals
ma, and derive everything

78
00:03:31,810 --> 00:03:35,230
from first principles.

79
00:03:35,230 --> 00:03:37,780
So we've been talking to
developers, both inside

80
00:03:37,780 --> 00:03:41,140
and outside of Google, and
taking a hard look at the app

81
00:03:41,140 --> 00:03:42,830
development experience.

82
00:03:42,830 --> 00:03:45,230
And we've realized
a couple of things.

83
00:03:45,230 --> 00:03:47,770
First, there are
peaks and valleys.

84
00:03:47,770 --> 00:03:51,550
Some aspects of app development
are better served by our APIs

85
00:03:51,550 --> 00:03:52,570
than others.

86
00:03:52,570 --> 00:03:56,470
For example, we think
RecyclerView is that the better

87
00:03:56,470 --> 00:03:57,830
end of that spectrum.

88
00:03:57,830 --> 00:04:02,020
So with RecyclerView, we didn't
say, hey, we give you events,

89
00:04:02,020 --> 00:04:03,810
and you can draw stuff.

90
00:04:03,810 --> 00:04:07,600
And in between you have a Turing
complete language, so good luck

91
00:04:07,600 --> 00:04:09,550
with everything else.

92
00:04:09,550 --> 00:04:12,640
On the other hand,
maybe Activity

93
00:04:12,640 --> 00:04:16,510
and Fragment Lifecycles belong
down in that dark shadowy place

94
00:04:16,510 --> 00:04:18,730
because there, I
think, too much of it

95
00:04:18,730 --> 00:04:21,790
is indeed left as an
exercise for the reader.

96
00:04:21,790 --> 00:04:24,730
And we want to fix that.

97
00:04:24,730 --> 00:04:27,250
So as we thought about this,
we realized the good solution

98
00:04:27,250 --> 00:04:29,930
has key properties.

99
00:04:29,930 --> 00:04:32,194
First, we have to solve
the right problems.

100
00:04:32,194 --> 00:04:33,860
This is going to be
a sustained effort--

101
00:04:33,860 --> 00:04:36,320
like sustained
for us on Android.

102
00:04:36,320 --> 00:04:38,410
But for the first cut,
we want to make sure

103
00:04:38,410 --> 00:04:39,910
that we are going
after the problems

104
00:04:39,910 --> 00:04:42,040
that every developer
faces, the things that

105
00:04:42,040 --> 00:04:45,040
are hard to do right right now.

106
00:04:45,040 --> 00:04:47,574
Again, app Lifecycles is
a really good example.

107
00:04:47,574 --> 00:04:49,240
If you don't get that
right in your app,

108
00:04:49,240 --> 00:04:51,236
nothing is going to
work on top of that.

109
00:04:51,236 --> 00:04:53,110
And that's true for your
app, but that's also

110
00:04:53,110 --> 00:04:55,026
true for the frameworks
we're trying to build.

111
00:04:55,026 --> 00:04:58,420
We have to get that right
before we can do anything else.

112
00:04:58,420 --> 00:05:00,370
Second, we have to
play well with others.

113
00:05:00,370 --> 00:05:02,830
We know that you all have huge
investments in your existing

114
00:05:02,830 --> 00:05:05,196
code bases, and we
can't create a model

115
00:05:05,196 --> 00:05:06,820
where the first thing
we say to you is,

116
00:05:06,820 --> 00:05:08,940
throw all that out
and start over.

117
00:05:08,940 --> 00:05:12,070
So we're trying to create APIs
that you can adopt a little bit

118
00:05:12,070 --> 00:05:15,580
at a time, and also
that interoperate well

119
00:05:15,580 --> 00:05:19,710
with other libraries
or other frameworks.

120
00:05:19,710 --> 00:05:22,054
Third, we want to
be more opinionated.

121
00:05:22,054 --> 00:05:23,970
We're going to take a
stronger, clearer stance

122
00:05:23,970 --> 00:05:26,000
on how to Android and
app the right way,

123
00:05:26,000 --> 00:05:27,100
at least as we see it.

124
00:05:27,100 --> 00:05:29,100
Now, this is all still optional.

125
00:05:29,100 --> 00:05:31,330
And if you already have
something that works for you,

126
00:05:31,330 --> 00:05:33,030
then great.

127
00:05:33,030 --> 00:05:36,210
But developers are telling us
that they want more guidance

128
00:05:36,210 --> 00:05:38,590
on how apps should be
built. And by the way,

129
00:05:38,590 --> 00:05:40,770
we're not changing any of
the laws of physics here,

130
00:05:40,770 --> 00:05:43,860
we're just layering some
higher level constructs on top.

131
00:05:43,860 --> 00:05:46,620
Because after all, F is
going to equal ma whether you

132
00:05:46,620 --> 00:05:49,860
believe it should or not.

133
00:05:49,860 --> 00:05:52,140
Next, it needs to scale.

134
00:05:52,140 --> 00:05:54,420
We want solutions that
are industrial strength,

135
00:05:54,420 --> 00:05:56,760
and that will scale to the
real world requirements

136
00:05:56,760 --> 00:05:58,474
of real world applications.

137
00:05:58,474 --> 00:06:01,140
We don't want to build something
that's awesome for Hello World,

138
00:06:01,140 --> 00:06:03,181
but then it's going to
collapse the first time it

139
00:06:03,181 --> 00:06:07,620
bumps into the messy
complexities of reality.

140
00:06:07,620 --> 00:06:09,410
And finally, reach.

141
00:06:09,410 --> 00:06:11,310
For this problem,
for making it easier

142
00:06:11,310 --> 00:06:13,830
for you to write Android
applications the right way--

143
00:06:13,830 --> 00:06:15,690
what we think is
the right way, we

144
00:06:15,690 --> 00:06:18,390
want to use libraries like
Support Lib wherever possible

145
00:06:18,390 --> 00:06:21,150
rather than adding new
APIs to the platform,

146
00:06:21,150 --> 00:06:24,030
because lets our solution
reach older versions of the OS

147
00:06:24,030 --> 00:06:26,745
as well.

148
00:06:26,745 --> 00:06:29,370
OK, so that's the background on
what we're trying to accomplish

149
00:06:29,370 --> 00:06:30,440
and why we're here.

150
00:06:30,440 --> 00:06:33,309
Now we'd like to introduce
Yigit, tool kit engineer

151
00:06:33,309 --> 00:06:35,600
extraordinaire, and he's
going to walk you through what

152
00:06:35,600 --> 00:06:36,860
we actually built. Thank you.

153
00:06:36,860 --> 00:06:37,290
[APPLAUSE]

154
00:06:37,290 --> 00:06:38,248
YIGIT BOYAR: All right.

155
00:06:38,248 --> 00:06:39,322
Thanks, Frank.

156
00:06:39,322 --> 00:06:43,610


157
00:06:43,610 --> 00:06:44,410
Hello everybody.

158
00:06:44,410 --> 00:06:46,930
So that was the background.

159
00:06:46,930 --> 00:06:49,050
What are we shipping today?

160
00:06:49,050 --> 00:06:51,210
The very first thing
we are shipping

161
00:06:51,210 --> 00:06:55,230
is an architecture guide
on developer Android com.

162
00:06:55,230 --> 00:06:58,440
Now for over years, you've
been asking us for our opinion.

163
00:06:58,440 --> 00:07:02,220
Like how do we think that an
application should be built?

164
00:07:02,220 --> 00:07:03,900
And this is that guide.

165
00:07:03,900 --> 00:07:06,270
So we believe that
it's very good,

166
00:07:06,270 --> 00:07:08,730
covers lots of
application cases.

167
00:07:08,730 --> 00:07:10,890
But even if you
have an architecture

168
00:07:10,890 --> 00:07:14,040
that you are comfortable
with, you can keep it.

169
00:07:14,040 --> 00:07:18,300
But you can probably learn
something from this guide.

170
00:07:18,300 --> 00:07:20,910
Second, we are shipping
a new set of libraries

171
00:07:20,910 --> 00:07:23,290
that we call
architecture components.

172
00:07:23,290 --> 00:07:24,900
These are more
fundamental components

173
00:07:24,900 --> 00:07:28,440
where you can build
your application on top.

174
00:07:28,440 --> 00:07:29,760
The first thing is Lifecycles.

175
00:07:29,760 --> 00:07:33,000
So this is the biggest developer
complaint that we have.

176
00:07:33,000 --> 00:07:35,610
Lifecycles are hard,
Lifecycles are hard.

177
00:07:35,610 --> 00:07:38,020
And we said, OK, we
should solve this problem.

178
00:07:38,020 --> 00:07:41,850
And the first level of this,
this new set of components.

179
00:07:41,850 --> 00:07:44,070
Second one is
Lifecycle-aware observables,

180
00:07:44,070 --> 00:07:46,860
which will go in detail
later, but this is basically

181
00:07:46,860 --> 00:07:51,730
things that can do something
based on the Lifecycle.

182
00:07:51,730 --> 00:07:54,810
Third, we are going to introduce
a lightweight ViewModel, which

183
00:07:54,810 --> 00:07:58,020
is all of our effort
to take out that code

184
00:07:58,020 --> 00:08:00,150
outside of your
Activities and Fragments,

185
00:08:00,150 --> 00:08:03,550
and put it somewhere else
where you can easily test it.

186
00:08:03,550 --> 00:08:06,630
Last but not least, we are
going to introduce a new object

187
00:08:06,630 --> 00:08:10,290
mapping library for SQLite.

188
00:08:10,290 --> 00:08:15,248
And all of this is available for
you today on Maven Google com.

189
00:08:15,248 --> 00:08:24,290
[APPLAUSE]

190
00:08:24,290 --> 00:08:25,790
Let's talk about Lifecycles.

191
00:08:25,790 --> 00:08:27,830
So what is what's
hard about Lifecycles?

192
00:08:27,830 --> 00:08:29,970
Why do we hear so many
complaints about that?

193
00:08:29,970 --> 00:08:31,510
Let's go through an example.

194
00:08:31,510 --> 00:08:33,440
Assume we have an
activity where we

195
00:08:33,440 --> 00:08:36,591
want to show the location
of the device on the screen.

196
00:08:36,591 --> 00:08:38,090
So you will try
something like this.

197
00:08:38,090 --> 00:08:41,280
You create a LocationListener
on Create method,

198
00:08:41,280 --> 00:08:43,250
you need to initialize
it with the context,

199
00:08:43,250 --> 00:08:46,520
and you have a callback that
it calls whenever the location

200
00:08:46,520 --> 00:08:48,800
changes, and you update the UI.

201
00:08:48,800 --> 00:08:51,230
Now, if you have ever written
an Android application,

202
00:08:51,230 --> 00:08:54,330
you know that this
code is never enough.

203
00:08:54,330 --> 00:08:57,440
You also need to go ahead and
override onStart, and then

204
00:08:57,440 --> 00:09:01,880
tell it to start, and override
onStop, and tell it to stop.

205
00:09:01,880 --> 00:09:04,040
You always need to
do this babysitting

206
00:09:04,040 --> 00:09:05,510
for these components.

207
00:09:05,510 --> 00:09:06,840
But this is acceptable.

208
00:09:06,840 --> 00:09:09,680
This a simple example,
this looks all right.

209
00:09:09,680 --> 00:09:11,750
But then your product
manager comes and says,

210
00:09:11,750 --> 00:09:12,560
oh, you know what?

211
00:09:12,560 --> 00:09:16,160
We need to first check the
user settings before enable--

212
00:09:16,160 --> 00:09:17,710
asking for a location.

213
00:09:17,710 --> 00:09:22,160
Then your developer says, OK,
sure, that's an easy change.

214
00:09:22,160 --> 00:09:25,570
I'm going to change this method
to first call this utility

215
00:09:25,570 --> 00:09:27,980
method, which probably
makes a web service call

216
00:09:27,980 --> 00:09:29,900
to check the user settings.

217
00:09:29,900 --> 00:09:32,030
And then if the
user is enrolled,

218
00:09:32,030 --> 00:09:34,160
then we want to start
the LocationListener.

219
00:09:34,160 --> 00:09:37,010
Which looks like a
very simple change,

220
00:09:37,010 --> 00:09:39,440
you will think this would
work, but let's look

221
00:09:39,440 --> 00:09:42,440
at what happens in that
activity's Lifecycle.

222
00:09:42,440 --> 00:09:43,990
So our activity was created.

223
00:09:43,990 --> 00:09:49,526
We said, OK, run start check
if the user status is enrolled.

224
00:09:49,526 --> 00:09:52,370
Then meanwhile, user wants
to rotate the device.

225
00:09:52,370 --> 00:09:54,930
Which, rotation means
a configuration change,

226
00:09:54,930 --> 00:09:58,430
which means Android is going
to recreate that activity.

227
00:09:58,430 --> 00:10:00,200
So in onStop, we
knew about this,

228
00:10:00,200 --> 00:10:03,292
and we said, OK,
location manager stop.

229
00:10:03,292 --> 00:10:05,780
And then the new
activity came, it also

230
00:10:05,780 --> 00:10:07,430
goes through the same thing.

231
00:10:07,430 --> 00:10:10,280
Looks all right, except
do you remember this call

232
00:10:10,280 --> 00:10:12,140
we made before?

233
00:10:12,140 --> 00:10:15,400
That little change, and then
it decides to come back.

234
00:10:15,400 --> 00:10:17,110
Hey, user is enrolled.

235
00:10:17,110 --> 00:10:18,080
And then what we did?

236
00:10:18,080 --> 00:10:20,790
We said, OK, then start.

237
00:10:20,790 --> 00:10:22,250
And you realize the [INAUDIBLE]?

238
00:10:22,250 --> 00:10:26,510
We called start after
calling on stop, which means

239
00:10:26,510 --> 00:10:28,700
our activity will live forever.

240
00:10:28,700 --> 00:10:31,130
We are going to observe
the location forever,

241
00:10:31,130 --> 00:10:32,257
the battery will drain.

242
00:10:32,257 --> 00:10:33,215
We will have sad users.

243
00:10:33,215 --> 00:10:37,078


244
00:10:37,078 --> 00:10:38,600
This is situation, right?

245
00:10:38,600 --> 00:10:40,220
We want to get rid of this.

246
00:10:40,220 --> 00:10:41,840
We want to put an end to this.

247
00:10:41,840 --> 00:10:43,950
So we said, OK, we
need to acknowledge--

248
00:10:43,950 --> 00:10:46,670
like as Mike mentioned,
we cannot change the laws,

249
00:10:46,670 --> 00:10:49,670
but we can make it easier
to deal with these things.

250
00:10:49,670 --> 00:10:52,430
So we decided to introduce
a new interface called

251
00:10:52,430 --> 00:10:53,970
LifecycleOwner.

252
00:10:53,970 --> 00:10:55,970
This is a thing
with a Lifecycle.

253
00:10:55,970 --> 00:10:58,400
Is your activity, is
your fragment-- or maybe

254
00:10:58,400 --> 00:11:02,270
you have your own UI framework,
whatever the container you have

255
00:11:02,270 --> 00:11:05,570
there as a LifecycleOwner.

256
00:11:05,570 --> 00:11:08,780
And we have these
LifecycleObservers,

257
00:11:08,780 --> 00:11:11,180
which are the things that
care about the Lifecycle.

258
00:11:11,180 --> 00:11:13,310
Like the
LocationListener we had,

259
00:11:13,310 --> 00:11:16,580
it cares about the Lifecycle,
it wants to stop itself

260
00:11:16,580 --> 00:11:18,680
if the Lifecycle is not active.

261
00:11:18,680 --> 00:11:21,130
So we said, OK, we
will acknowledge this.

262
00:11:21,130 --> 00:11:23,600
And we have a
LifecycleObservers.

263
00:11:23,600 --> 00:11:26,090
And we'll go through the
code through our activity.

264
00:11:26,090 --> 00:11:30,080
Now we make our activity extend
the LifecycleActivity class.

265
00:11:30,080 --> 00:11:33,320
This is just a temporary
class until these components

266
00:11:33,320 --> 00:11:34,410
reach 1.0.

267
00:11:34,410 --> 00:11:35,900
Then everything
in Support Library

268
00:11:35,900 --> 00:11:39,980
will implement this
LifecycleOwner interface.

269
00:11:39,980 --> 00:11:42,550
Inside of our activity,
when we initialize

270
00:11:42,550 --> 00:11:45,710
our LocationListener,
we are going to tell it,

271
00:11:45,710 --> 00:11:48,240
this is the Lifecycle
you care about.

272
00:11:48,240 --> 00:11:50,390
And that's all we will do.

273
00:11:50,390 --> 00:11:54,410
But as it's the same, it
calls back the update UI.

274
00:11:54,410 --> 00:11:57,020
So how can we change
our LocationListener

275
00:11:57,020 --> 00:12:00,890
to take advantage
of this Lifecycle?

276
00:12:00,890 --> 00:12:03,500
Oh, we do the same thing
for the UserStatus as well.

277
00:12:03,500 --> 00:12:06,240


278
00:12:06,240 --> 00:12:08,880
So there's some boilerplate
code here to get the fields.

279
00:12:08,880 --> 00:12:10,950
It doesn't really
matter, but we have

280
00:12:10,950 --> 00:12:14,850
this enabled method which gets
called if the user is enrolled.

281
00:12:14,850 --> 00:12:16,500
Inside this enabled
method, now we

282
00:12:16,500 --> 00:12:18,420
want to start
listening to location

283
00:12:18,420 --> 00:12:21,360
only if the activity is started.

284
00:12:21,360 --> 00:12:23,040
Now you can do this.

285
00:12:23,040 --> 00:12:26,590
You can say, what is my current
state, which is amazing.

286
00:12:26,590 --> 00:12:29,370
We didn't have
this API until now.

287
00:12:29,370 --> 00:12:32,010
Well now you can.

288
00:12:32,010 --> 00:12:34,110
So OK, that was a simple change.

289
00:12:34,110 --> 00:12:36,510
But we also get
notified, what if we get

290
00:12:36,510 --> 00:12:38,710
enrolled when the activity
was in back state,

291
00:12:38,710 --> 00:12:40,800
and user comes back
to the activity.

292
00:12:40,800 --> 00:12:43,290
Now we should actually
start the LocationManager.

293
00:12:43,290 --> 00:12:46,290
For this, we want to
observe that Lifecycle.

294
00:12:46,290 --> 00:12:48,690
To do that, we implement
this interface,

295
00:12:48,690 --> 00:12:50,670
which allows us to
write these methods.

296
00:12:50,670 --> 00:12:52,710
You can annotate
the methods saying

297
00:12:52,710 --> 00:12:56,152
that, if ON_START
happens, call this method.

298
00:12:56,152 --> 00:12:58,360
And the new components will
take care of calling you.

299
00:12:58,360 --> 00:13:00,660
So if you are already
enabled, now you

300
00:13:00,660 --> 00:13:03,540
start, and ON_STOP
you disconnect.

301
00:13:03,540 --> 00:13:06,700
And last but not least, if
the activity is destroyed

302
00:13:06,700 --> 00:13:09,220
there is nothing you want
to do with that activity

303
00:13:09,220 --> 00:13:11,796
so you can unregister.

304
00:13:11,796 --> 00:13:13,920
So now you might be asking
yourself, well, you just

305
00:13:13,920 --> 00:13:16,710
moved those ON_START, ON_STOP
methods from the activity

306
00:13:16,710 --> 00:13:18,450
into this Location Manager.

307
00:13:18,450 --> 00:13:20,150
How come it is simpler?

308
00:13:20,150 --> 00:13:22,250
It's simpler because
those methods

309
00:13:22,250 --> 00:13:23,610
live in the right place.

310
00:13:23,610 --> 00:13:27,690
It's the Location Manager which
cares about the Lifecycle.

311
00:13:27,690 --> 00:13:30,780
So it should be able to
do it without the activity

312
00:13:30,780 --> 00:13:32,460
babysitting itself.

313
00:13:32,460 --> 00:13:34,170
I'm sure if you look
at your code today,

314
00:13:34,170 --> 00:13:37,260
your activity ON_START, ON_STOP
methods are like, at least 20,

315
00:13:37,260 --> 00:13:38,730
30 lines of code.

316
00:13:38,730 --> 00:13:42,060
We want them to be
zero lines of code.

317
00:13:42,060 --> 00:13:43,800
If we go back to
activity, I want

318
00:13:43,800 --> 00:13:45,780
to point out something that--

319
00:13:45,780 --> 00:13:49,260
look, in onCreate, we
initialized these components.

320
00:13:49,260 --> 00:13:50,580
And that's all we did.

321
00:13:50,580 --> 00:13:53,230
We didn't override, we
didn't ON_STOP, ON_START,

322
00:13:53,230 --> 00:13:55,020
we don't override
any of those things

323
00:13:55,020 --> 00:13:59,630
because the Location Manager
is a Lifecycle aware component

324
00:13:59,630 --> 00:14:01,875
now.

325
00:14:01,875 --> 00:14:03,990
So it's a new concept
we want to introduce.

326
00:14:03,990 --> 00:14:08,130
A Lifecycle aware component in
a component can get a Lifecycle,

327
00:14:08,130 --> 00:14:09,170
and do the right things.

328
00:14:09,170 --> 00:14:12,210
It can take care of itself
so that your activity,

329
00:14:12,210 --> 00:14:15,120
you can just initialize
it and forget about it.

330
00:14:15,120 --> 00:14:19,060
You know that's not
going to leak you.

331
00:14:19,060 --> 00:14:22,480
Now, of course, it was like
more of moving the complex

332
00:14:22,480 --> 00:14:24,520
from activity to the
Location Manager,

333
00:14:24,520 --> 00:14:27,310
and then it still needs
to deal with Lifecycle.

334
00:14:27,310 --> 00:14:29,190
We said, OK, what do we want?

335
00:14:29,190 --> 00:14:32,540
It's nice to be able to
do that, but we want more.

336
00:14:32,540 --> 00:14:35,230
We want a very convenient
to handle this common case.

337
00:14:35,230 --> 00:14:38,390
It's very common that your
activity or fragment, it

338
00:14:38,390 --> 00:14:41,830
observes some data, and
whenever that data changes,

339
00:14:41,830 --> 00:14:43,300
it wants to refresh itself.

340
00:14:43,300 --> 00:14:46,910
It happens basically
almost every single UI.

341
00:14:46,910 --> 00:14:49,870
And we want to share resources
across multiple fragments

342
00:14:49,870 --> 00:14:51,250
or activities.

343
00:14:51,250 --> 00:14:54,580
The location of the device
is the same from fragment

344
00:14:54,580 --> 00:14:55,240
to fragment.

345
00:14:55,240 --> 00:14:57,040
If you have two
fragments, why do you

346
00:14:57,040 --> 00:15:01,610
need to create two listeners
to listen to the same location?

347
00:15:01,610 --> 00:15:05,080
Hence, we created this
new LiveData clause.

348
00:15:05,080 --> 00:15:06,600
Let's look at that.

349
00:15:06,600 --> 00:15:10,390
So LiveData is a data holder,
it just holds some data.

350
00:15:10,390 --> 00:15:13,690
It's like an observable, but
the tricky thing about LiveData

351
00:15:13,690 --> 00:15:15,760
is that it is Lifecycle aware.

352
00:15:15,760 --> 00:15:18,310
It understands about Lifecycles.

353
00:15:18,310 --> 00:15:20,820
Because it understands
about Lifecycles,

354
00:15:20,820 --> 00:15:22,850
it automatically
manages subscriptions.

355
00:15:22,850 --> 00:15:25,220
So very similar to
the previous example,

356
00:15:25,220 --> 00:15:29,290
if you are observing a LiveData,
you don't need to unsubscribe,

357
00:15:29,290 --> 00:15:33,040
the right things will
happen in the right times.

358
00:15:33,040 --> 00:15:37,660
So if that LocationListener
was a LiveData, and a singleton

359
00:15:37,660 --> 00:15:40,000
because location
is singleton, we

360
00:15:40,000 --> 00:15:41,800
could write the code like this--

361
00:15:41,800 --> 00:15:43,930
get distance, start observing.

362
00:15:43,930 --> 00:15:47,280
And when you observe, you
say, this is my Lifecycle.

363
00:15:47,280 --> 00:15:48,280
This all you need to do.

364
00:15:48,280 --> 00:15:51,880
Before on Android, if you were
observing something singleton

365
00:15:51,880 --> 00:15:55,180
from an activity, everyone
will give minus two

366
00:15:55,180 --> 00:15:56,650
to that code review.

367
00:15:56,650 --> 00:15:57,805
Now you can do this.

368
00:15:57,805 --> 00:16:01,600
This is safe,
nothing ever leaks.

369
00:16:01,600 --> 00:16:03,790
So if you want to change
your LocationListener

370
00:16:03,790 --> 00:16:07,430
to use this new API, we get
rid of the unnecessary things.

371
00:16:07,430 --> 00:16:09,590
All we need is a
context to connect.

372
00:16:09,590 --> 00:16:15,540
What we say, this is a LiveData,
this a LiveData of a location.

373
00:16:15,540 --> 00:16:18,110
And we get these
two new methods.

374
00:16:18,110 --> 00:16:20,520
One of two says
onActive, which means

375
00:16:20,520 --> 00:16:22,920
you have an active observer.

376
00:16:22,920 --> 00:16:24,475
And the other one
says onInactive,

377
00:16:24,475 --> 00:16:27,555
which means you don't have
any observers that are active.

378
00:16:27,555 --> 00:16:30,360
Now at this point, you're
probably asking yourself,

379
00:16:30,360 --> 00:16:32,590
what is an active observer?

380
00:16:32,590 --> 00:16:34,290
Well, we define
an active observer

381
00:16:34,290 --> 00:16:37,710
as an observer that's in the
STARTED or RESUMED state, which

382
00:16:37,710 --> 00:16:40,440
is like an activity user
is currently seeing.

383
00:16:40,440 --> 00:16:43,020
So if you have an observer
in the back stack,

384
00:16:43,020 --> 00:16:45,300
there's no reason to
put this inactive.

385
00:16:45,300 --> 00:16:47,190
There's no reason to
update that activity

386
00:16:47,190 --> 00:16:49,950
because user will never, ever
see what's going on there.

387
00:16:49,950 --> 00:16:53,390


388
00:16:53,390 --> 00:16:56,130
So inside our connect
method, all we need to do

389
00:16:56,130 --> 00:16:58,540
is, whenever the system
Location Manager sends us

390
00:16:58,540 --> 00:17:02,120
a new location, we call
setValue on ourselves.

391
00:17:02,120 --> 00:17:05,589
Then the LiveData knows which
are the active observers,

392
00:17:05,589 --> 00:17:08,410
and delivers the data
to those observers.

393
00:17:08,410 --> 00:17:11,930
Or if one of the observers
was on the back stack

394
00:17:11,930 --> 00:17:14,290
and then becomes
visible again, LiveData

395
00:17:14,290 --> 00:17:17,079
takes care of sending the latest
data back to that observer.

396
00:17:17,079 --> 00:17:19,608


397
00:17:19,608 --> 00:17:22,858
And then we can make our
LocationListener singleton

398
00:17:22,858 --> 00:17:26,019
because well, we don't
need multiple instances.

399
00:17:26,020 --> 00:17:30,400
So if we look at LiveData, it
is a Lifecycle aware Observable.

400
00:17:30,400 --> 00:17:32,520
It is very simple start
and stop semantics.

401
00:17:32,520 --> 00:17:34,650
Doesn't matter how many
observers you have,

402
00:17:34,650 --> 00:17:39,740
or what state they are, we merge
all of it into one Lifecycle.

403
00:17:39,740 --> 00:17:42,000
And it doesn't have any
activities or fragments

404
00:17:42,000 --> 00:17:44,620
inside it, but it works
with both of them.

405
00:17:44,620 --> 00:17:47,460
And is also really used to
test LiveData because it's

406
00:17:47,460 --> 00:17:49,080
kind of Android free.

407
00:17:49,080 --> 00:17:52,720
And if you know about this
infamous FragmentTransaction

408
00:17:52,720 --> 00:17:56,670
exception, we guarantee that
your observer will never,

409
00:17:56,670 --> 00:17:59,750
ever be called in a state
where you cannot run

410
00:17:59,750 --> 00:18:01,260
a FragmentTransaction.

411
00:18:01,260 --> 00:18:03,780
So this is very, very
specifically designed

412
00:18:03,780 --> 00:18:08,100
to work well with your
Activities and Fragments.

413
00:18:08,100 --> 00:18:11,520
OK, let's think about
configuration changes.

414
00:18:11,520 --> 00:18:14,460
Now, that example was easy
because location is global,

415
00:18:14,460 --> 00:18:17,550
but most of the time,
the data belongs to a UI.

416
00:18:17,550 --> 00:18:22,770
So if we had an activity
where we show a user profile,

417
00:18:22,770 --> 00:18:24,660
and we implemented
a web service that

418
00:18:24,660 --> 00:18:28,260
can return the data as a
LiveData which we can safely

419
00:18:28,260 --> 00:18:32,580
observe without risking
leaking overactivity,

420
00:18:32,580 --> 00:18:33,470
this all looks nice.

421
00:18:33,470 --> 00:18:35,030
You will never
leak this activity,

422
00:18:35,030 --> 00:18:36,390
it will work very well.

423
00:18:36,390 --> 00:18:40,340
Except, what happens if the
user rotates to the device?

424
00:18:40,340 --> 00:18:42,850
Let's look at the
LifeCycle graph again.

425
00:18:42,850 --> 00:18:44,790
So activity is
created, it saves, OK.

426
00:18:44,790 --> 00:18:46,752
Fetch the user.

427
00:18:46,752 --> 00:18:48,460
And then while you
are fetching the user,

428
00:18:48,460 --> 00:18:51,390
user decides, oh, I want
to rotate the phone.

429
00:18:51,390 --> 00:18:53,130
And then that
activity is destroyed.

430
00:18:53,130 --> 00:18:55,740
Luckily we don't leak
it, which is great.

431
00:18:55,740 --> 00:18:57,810
But then the new
activity starts,

432
00:18:57,810 --> 00:18:59,620
which makes this new call.

433
00:18:59,620 --> 00:19:02,160
Now, this is OK, but not great.

434
00:19:02,160 --> 00:19:03,640
What do we want?

435
00:19:03,640 --> 00:19:05,700
We want to actually
retain that data, right?

436
00:19:05,700 --> 00:19:09,870
We are already making that
request, why remake it?

437
00:19:09,870 --> 00:19:12,780
So we want our graph
to look like this.

438
00:19:12,780 --> 00:19:14,640
So if the new activity
comes, we should

439
00:19:14,640 --> 00:19:18,330
be able to give it back the
same view model, which is

440
00:19:18,330 --> 00:19:20,340
a new class called ViewModel.

441
00:19:20,340 --> 00:19:22,290
So we are introducing
this new class

442
00:19:22,290 --> 00:19:23,760
very specific to
this thing, where

443
00:19:23,760 --> 00:19:27,210
you should put the data
inside your activities

444
00:19:27,210 --> 00:19:30,940
into the ViewModel, and make
the activities data-free.

445
00:19:30,940 --> 00:19:33,000
So if you want to
change this activity,

446
00:19:33,000 --> 00:19:36,910
we create this new class, it
extends the VewModel class.

447
00:19:36,910 --> 00:19:41,830
Whatever data we had inside
the activity, we move it there.

448
00:19:41,830 --> 00:19:45,630
And in the ViewModel, all we do
is, inside the getUser method,

449
00:19:45,630 --> 00:19:48,790
if this is the first goal,
get it from the web service.

450
00:19:48,790 --> 00:19:51,800
Otherwise, return
to existing value.

451
00:19:51,800 --> 00:19:53,220
Now, super simple.

452
00:19:53,220 --> 00:19:55,800
And inside our activity, we
get rid of all that code.

453
00:19:55,800 --> 00:19:58,590
We say, get the
ViewModelProviders.of this.

454
00:19:58,590 --> 00:20:01,620
So each activity or a fragment
has a ViewModelProvider

455
00:20:01,620 --> 00:20:04,680
that you can obtain, and
that ViewModelProvider knows

456
00:20:04,680 --> 00:20:06,510
how to give you the ViewModel.

457
00:20:06,510 --> 00:20:08,880
So when you call
get MyViewModel,

458
00:20:08,880 --> 00:20:10,530
the very first time
you make this call,

459
00:20:10,530 --> 00:20:11,940
we will give you a new instance.

460
00:20:11,940 --> 00:20:13,780
When the rotated
activity comes back,

461
00:20:13,780 --> 00:20:16,760
it's going to reconnect
to the same ViewModel.

462
00:20:16,760 --> 00:20:19,432
And then the rest of
the code is the same.

463
00:20:19,432 --> 00:20:22,318
[APPLAUSE]

464
00:20:22,318 --> 00:20:28,580


465
00:20:28,580 --> 00:20:31,060
So if you look at the
Lifecycle, this is how it looks.

466
00:20:31,060 --> 00:20:32,040
This is what we wanted.

467
00:20:32,040 --> 00:20:35,800
The new activity is
started, it reconnects.

468
00:20:35,800 --> 00:20:38,140
And when the new
activity is finished,

469
00:20:38,140 --> 00:20:41,050
like when we don't have anything
to do with that activity,

470
00:20:41,050 --> 00:20:42,580
and then we go
and tell ViewModel

471
00:20:42,580 --> 00:20:44,350
that it's not needed anymore.

472
00:20:44,350 --> 00:20:48,340
This is actually the only
method in the ViewModel class.

473
00:20:48,340 --> 00:20:49,570
So this is very simple.

474
00:20:49,570 --> 00:20:51,640
So if we look at
Lifecycles, they

475
00:20:51,640 --> 00:20:53,310
hold the data for the activity.

476
00:20:53,310 --> 00:20:56,500
They survive
configuration changes.

477
00:20:56,500 --> 00:20:58,930
They should never,
ever reference views

478
00:20:58,930 --> 00:21:00,870
because they [INAUDIBLE]
leave the activities.

479
00:21:00,870 --> 00:21:03,430
So you cannot reference
back to the activity.

480
00:21:03,430 --> 00:21:05,640
That's why you use
things like LiveData,

481
00:21:05,640 --> 00:21:08,550
Rx Java, or
datamining observables

482
00:21:08,550 --> 00:21:10,270
to do that communication.

483
00:21:10,270 --> 00:21:12,730
And this is what our
activity talks-- it always

484
00:21:12,730 --> 00:21:15,070
talks to the ViewModel.

485
00:21:15,070 --> 00:21:19,210
Now, another big
topic is persistence.

486
00:21:19,210 --> 00:21:22,000
Now, we know that to write a
good, responsive Android app,

487
00:21:22,000 --> 00:21:24,860
you need to save
the data on disk.

488
00:21:24,860 --> 00:21:27,700
If you come to Android, there's
this three major APIs we have.

489
00:21:27,700 --> 00:21:29,980
One of them is content
providers, which

490
00:21:29,980 --> 00:21:32,320
is to talk between processes.

491
00:21:32,320 --> 00:21:35,530
It really has nothing to do
with persistence, in reality.

492
00:21:35,530 --> 00:21:37,510
The other one is
shared preferences,

493
00:21:37,510 --> 00:21:40,090
which saves the data in XML.

494
00:21:40,090 --> 00:21:43,190
So you can only put very
little data into that.

495
00:21:43,190 --> 00:21:44,800
And the last one
is SQLite, which

496
00:21:44,800 --> 00:21:48,160
is something we have been
shipping since Android 1.

497
00:21:48,160 --> 00:21:49,720
So you know you
need to use SQLite

498
00:21:49,720 --> 00:21:51,890
if you want to save big data.

499
00:21:51,890 --> 00:21:55,330
And so you go into the
developer.android.com/ This is

500
00:21:55,330 --> 00:21:57,960
the very first saving
your data slide.

501
00:21:57,960 --> 00:22:00,130
This is so confusing.

502
00:22:00,130 --> 00:22:01,642
This is very sad.

503
00:22:01,642 --> 00:22:03,370
[LAUGHTER]

504
00:22:03,370 --> 00:22:06,190
So is it-- OK, we want
to make this less sad.

505
00:22:06,190 --> 00:22:07,960
We want to make it happy.

506
00:22:07,960 --> 00:22:10,060
So we'll look at
the example, right?

507
00:22:10,060 --> 00:22:11,740
So there's-- on top,
it tries to say,

508
00:22:11,740 --> 00:22:15,670
I want to select these three
columns with this constraint,

509
00:22:15,670 --> 00:22:17,950
and I want to order
them like this.

510
00:22:17,950 --> 00:22:20,670
This actually really,
really simple SQL query,

511
00:22:20,670 --> 00:22:22,210
but you need to
write all this code.

512
00:22:22,210 --> 00:22:24,160
Plus, this code
doesn't even show where

513
00:22:24,160 --> 00:22:27,720
you define all those constants.

514
00:22:27,720 --> 00:22:29,430
So what do we really want?

515
00:22:29,430 --> 00:22:32,060
We want to get rid of that
boilerplate-free code.

516
00:22:32,060 --> 00:22:34,890
When you are writing Java,
if you make a typo in Java,

517
00:22:34,890 --> 00:22:36,630
it doesn't compile right.

518
00:22:36,630 --> 00:22:39,010
We want the same thing for SQL.

519
00:22:39,010 --> 00:22:42,000
We still want to use SQLite,
because on every single Android

520
00:22:42,000 --> 00:22:43,740
device it's a proven technology.

521
00:22:43,740 --> 00:22:46,230
We know it works very well.

522
00:22:46,230 --> 00:22:48,280
But we want the compile
time verification.

523
00:22:48,280 --> 00:22:49,970
So we don't want the
boilerplate code,

524
00:22:49,970 --> 00:22:52,480
we want to compile
time verification.

525
00:22:52,480 --> 00:22:56,220
So we said, well-- we came up
with Room, which is an object

526
00:22:56,220 --> 00:22:59,649
mapping library for SQLite.

527
00:22:59,649 --> 00:23:05,800
[APPLAUSE]

528
00:23:05,800 --> 00:23:08,210
So if you look at
this query, we said,

529
00:23:08,210 --> 00:23:10,770
OK, let's move this query
inside the annotation.

530
00:23:10,770 --> 00:23:12,610
We like annotations.

531
00:23:12,610 --> 00:23:14,560
And we have this
feed object, which we

532
00:23:14,560 --> 00:23:16,360
want to save in the database.

533
00:23:16,360 --> 00:23:19,270
I want to put that query
inside an interface.

534
00:23:19,270 --> 00:23:21,280
You want to create the FeedDao--

535
00:23:21,280 --> 00:23:24,040
the Dao stands for
Data Access Object.

536
00:23:24,040 --> 00:23:27,430
Usually in database, the best
practice to put your database

537
00:23:27,430 --> 00:23:29,350
access into certain interfaces.

538
00:23:29,350 --> 00:23:32,252
Then we just need to tell
the Room, this is a Dow.

539
00:23:32,252 --> 00:23:34,360
Tell Room this is an entity.

540
00:23:34,360 --> 00:23:37,960
And finally, we had a
database class which says,

541
00:23:37,960 --> 00:23:41,050
I have these entities-- so
you have multiple entities,

542
00:23:41,050 --> 00:23:45,240
and I have these data access
objects, as you saw them.

543
00:23:45,240 --> 00:23:46,210
This is all you write.

544
00:23:46,210 --> 00:23:48,760
Once you write that, you can
get an implementation of it

545
00:23:48,760 --> 00:23:49,590
from Room.

546
00:23:49,590 --> 00:23:52,750
It's very similar to how
you use Retrofit or Dagger--

547
00:23:52,750 --> 00:23:57,080
you define the interfaces, we
provide the implementation.

548
00:23:57,080 --> 00:23:59,740
Now, once we know
this is a Dow, we

549
00:23:59,740 --> 00:24:01,210
can do these shortcut methods.

550
00:24:01,210 --> 00:24:05,350
Like, insert these items, or
delete these items, or update--

551
00:24:05,350 --> 00:24:06,930
a bunch of shortcut methods.

552
00:24:06,930 --> 00:24:08,710
And you can press
multiple parameters.

553
00:24:08,710 --> 00:24:11,115
As long as you can read
it and it makes sense,

554
00:24:11,115 --> 00:24:13,930
Room will understand it.

555
00:24:13,930 --> 00:24:16,000
But the most
important part of Room

556
00:24:16,000 --> 00:24:18,680
is, it understands your SQL.

557
00:24:18,680 --> 00:24:20,320
So the part-- all
those constants

558
00:24:20,320 --> 00:24:23,630
I mentioned we defined to
get compile time guarantees,

559
00:24:23,630 --> 00:24:26,560
Room actually gives
all of this for free.

560
00:24:26,560 --> 00:24:28,380
So when Room sees
this query, says,

561
00:24:28,380 --> 00:24:31,060
OK, you are receiving
these three columns

562
00:24:31,060 --> 00:24:34,900
from this table where the
title looks like this keyword.

563
00:24:34,900 --> 00:24:36,705
Where is this
keyword coming from?

564
00:24:36,705 --> 00:24:38,710
Oh, it's coming from
the function parameters.

565
00:24:38,710 --> 00:24:39,567
Makes sense.

566
00:24:39,567 --> 00:24:40,900
And what does it want to return?

567
00:24:40,900 --> 00:24:42,970
It wants to return
a list of feeds.

568
00:24:42,970 --> 00:24:45,330
And then Room goes and checks.

569
00:24:45,330 --> 00:24:47,980
Does the columns
returned match the object

570
00:24:47,980 --> 00:24:49,690
the user wants to return?

571
00:24:49,690 --> 00:24:53,812
And once they're equal, it says,
OK, I can generate this code.

572
00:24:53,812 --> 00:24:55,270
You can have even
say, select star.

573
00:24:55,270 --> 00:24:56,600
You don't need to list them.

574
00:24:56,600 --> 00:25:00,190
Room really, really
understand your query.

575
00:25:00,190 --> 00:25:03,130
You can even join 10
tables, it will still work.

576
00:25:03,130 --> 00:25:05,020
But what if you made a typo?

577
00:25:05,020 --> 00:25:07,750
Instead of saying feed
table you wrote feeds.

578
00:25:07,750 --> 00:25:10,750
Now, if this happens,
Room is going to give you

579
00:25:10,750 --> 00:25:12,940
an error at compile time.

580
00:25:12,940 --> 00:25:15,040
So it goes out and
verifies your query

581
00:25:15,040 --> 00:25:17,080
against the schema
you have defined,

582
00:25:17,080 --> 00:25:19,562
and it tells you if
something is wrong.

583
00:25:19,562 --> 00:25:22,508
[APPLAUSE]

584
00:25:22,508 --> 00:25:27,797


585
00:25:27,797 --> 00:25:29,380
But that's not the
only thing it does.

586
00:25:29,380 --> 00:25:30,860
So if you said--

587
00:25:30,860 --> 00:25:34,070
if your query is correct, you
want to fetch ID and title.

588
00:25:34,070 --> 00:25:35,870
This said, well,
it's query, but you

589
00:25:35,870 --> 00:25:37,350
want to return it as a string.

590
00:25:37,350 --> 00:25:40,460
And then Room says, well, you
are returning two columns,

591
00:25:40,460 --> 00:25:42,260
but you only have one string.

592
00:25:42,260 --> 00:25:43,320
That doesn't make sense.

593
00:25:43,320 --> 00:25:46,800
And it's going to give you
a compile time error again.

594
00:25:46,800 --> 00:25:49,220
And there's a really nice
way to fix this in Room.

595
00:25:49,220 --> 00:25:51,095
You can basically
create any Java class.

596
00:25:51,095 --> 00:25:52,580
It doesn't need
to be annotating,

597
00:25:52,580 --> 00:25:55,170
there's nothing special
about that Pojo,

598
00:25:55,170 --> 00:25:57,080
and tell Room to return it.

599
00:25:57,080 --> 00:25:59,780
As long as whatever
query it returns

600
00:25:59,780 --> 00:26:01,880
matches what you
want it to return,

601
00:26:01,880 --> 00:26:05,250
Room will write
the code for you.

602
00:26:05,250 --> 00:26:07,470
And observability, which
is very important, right?

603
00:26:07,470 --> 00:26:09,390
If you have a query
like this, now you're

604
00:26:09,390 --> 00:26:11,460
showing lists of
feeds, you obviously

605
00:26:11,460 --> 00:26:14,295
want to get notified
when the data changes.

606
00:26:14,295 --> 00:26:17,842
And in Room, if you want to
do this, all you have to do

607
00:26:17,842 --> 00:26:19,290
is tell it.

608
00:26:19,290 --> 00:26:22,980
Tell it to return a LiveData,
and it will do it for you.

609
00:26:22,980 --> 00:26:26,400
Because it knows your query,
it knows what things affect it.

610
00:26:26,400 --> 00:26:29,520
So it can let you know
if that query changes.

611
00:26:29,520 --> 00:26:32,280
And this is the part where all
these architectural components

612
00:26:32,280 --> 00:26:33,750
work well together.

613
00:26:33,750 --> 00:26:36,640
Room already knows
about LiveData.

614
00:26:36,640 --> 00:26:40,340
So your ViewModel, all you would
write is-- from the data is,

615
00:26:40,340 --> 00:26:42,600
call this query, and
this all it will do.

616
00:26:42,600 --> 00:26:46,650
Whenever that data changes,
your UI will get a new update.

617
00:26:46,650 --> 00:26:49,470
And it only happens
if the UI is visible.

618
00:26:49,470 --> 00:26:52,958
Last but not least, Room
also supports RxJava 2.

619
00:26:52,958 --> 00:26:55,448
[APPLAUSE]

620
00:26:55,448 --> 00:27:01,930


621
00:27:01,930 --> 00:27:04,390
OK, if we look at
Room in a nutshell,

622
00:27:04,390 --> 00:27:06,730
it writes the
boilerplate code for you.

623
00:27:06,730 --> 00:27:08,050
It has full SQLite support.

624
00:27:08,050 --> 00:27:10,990
You can just write in
SQLite, there's no builders.

625
00:27:10,990 --> 00:27:14,070
It verifies your
queries at compile time.

626
00:27:14,070 --> 00:27:17,350
It incentivizes best
practices, which helps you

627
00:27:17,350 --> 00:27:19,480
with testing migrations.

628
00:27:19,480 --> 00:27:23,020
And it's also observable
out of the box.

629
00:27:23,020 --> 00:27:28,000
OK, architecture,
our last topic today.

630
00:27:28,000 --> 00:27:30,000
So where we started, right?

631
00:27:30,000 --> 00:27:31,860
And now, you might
be asking yourselves,

632
00:27:31,860 --> 00:27:34,335
what has changed
in 2017 that you

633
00:27:34,335 --> 00:27:36,930
are talking about architecture?

634
00:27:36,930 --> 00:27:38,740
Well, actually
nothing has changed.

635
00:27:38,740 --> 00:27:40,560
We've been talking
about this topic a lot.

636
00:27:40,560 --> 00:27:44,460
Adam Powell and I gave a
lot of talks on this topic.

637
00:27:44,460 --> 00:27:49,050
There's even a talk from 2010
which I watch as a developer.

638
00:27:49,050 --> 00:27:51,630
So this is a topic we have
been more clear about.

639
00:27:51,630 --> 00:27:54,720
But what is missing was
a well-defined reference

640
00:27:54,720 --> 00:27:56,022
architecture.

641
00:27:56,022 --> 00:27:57,480
So it's what we
are shipping today.

642
00:27:57,480 --> 00:27:59,370
If you go to
developer.android.com today

643
00:27:59,370 --> 00:28:01,680
after the session,
there's a section

644
00:28:01,680 --> 00:28:05,246
about how to architect
an Android application.

645
00:28:05,246 --> 00:28:08,697
[APPLAUSE]

646
00:28:08,697 --> 00:28:13,640


647
00:28:13,640 --> 00:28:15,890
So by the way, this
is a reference guide.

648
00:28:15,890 --> 00:28:17,780
This is not your religious book.

649
00:28:17,780 --> 00:28:20,600
We believe this is a very good
way to write applications,

650
00:28:20,600 --> 00:28:24,320
but you don't need to
follow it line by line.

651
00:28:24,320 --> 00:28:27,400
So I'm going to briefly go
through this architecture,

652
00:28:27,400 --> 00:28:28,960
but if you get
lost, don't worry.

653
00:28:28,960 --> 00:28:31,950
We have all of this documented
on developer Android com

654
00:28:31,950 --> 00:28:34,264
with sample applications.

655
00:28:34,264 --> 00:28:35,680
So we think that
an application is

656
00:28:35,680 --> 00:28:37,300
composed of four main things--

657
00:28:37,300 --> 00:28:41,680
there's UI controllers, the
view models, a repository,

658
00:28:41,680 --> 00:28:43,030
and the data sources.

659
00:28:43,030 --> 00:28:45,640
So let's look at
these in detail.

660
00:28:45,640 --> 00:28:47,980
UI controllers are
your activities,

661
00:28:47,980 --> 00:28:51,100
fragments, custom views.

662
00:28:51,100 --> 00:28:52,750
They have really simple tasks.

663
00:28:52,750 --> 00:28:55,270
They observe the
fields of the ViewModel

664
00:28:55,270 --> 00:28:56,720
and update themselves.

665
00:28:56,720 --> 00:28:58,540
And they want more
responsibility.

666
00:28:58,540 --> 00:29:01,540
Whenever user takes
an action on the UI,

667
00:29:01,540 --> 00:29:04,450
they understand that action,
and call the ViewModel

668
00:29:04,450 --> 00:29:07,540
to express whatever
the user wanted to do.

669
00:29:07,540 --> 00:29:10,390
If you go to our view
model, view model

670
00:29:10,390 --> 00:29:13,450
is the one which prepares
the data for the UI,

671
00:29:13,450 --> 00:29:14,480
and holds onto it.

672
00:29:14,480 --> 00:29:16,740
This is where the
data for the UI lives.

673
00:29:16,740 --> 00:29:20,050
View model knows how
to get that data.

674
00:29:20,050 --> 00:29:21,949
Usually it has LiveData.

675
00:29:21,949 --> 00:29:23,740
If you are using Rx
Java, it is observable,

676
00:29:23,740 --> 00:29:26,940
or datamining observables.

677
00:29:26,940 --> 00:29:28,830
It survives
configuration changes.

678
00:29:28,830 --> 00:29:32,200
That's why we put the
data into the view models.

679
00:29:32,200 --> 00:29:33,680
And it is also the gateway.

680
00:29:33,680 --> 00:29:37,040
You can also consider it
as, your UI controller only

681
00:29:37,040 --> 00:29:39,230
ever talks to the
view model to reach

682
00:29:39,230 --> 00:29:42,690
to the rest of the application.

683
00:29:42,690 --> 00:29:44,360
And then what's the repository?

684
00:29:44,360 --> 00:29:47,100
Now, the view model
serves as a data store

685
00:29:47,100 --> 00:29:48,920
for your UI controller, right?

686
00:29:48,920 --> 00:29:51,060
Repository saves
it as a data store

687
00:29:51,060 --> 00:29:53,520
for all of your application.

688
00:29:53,520 --> 00:29:56,070
So it's the complete
data model for the app,

689
00:29:56,070 --> 00:29:58,560
and it provides this
data with simple APIs

690
00:29:58,560 --> 00:30:00,210
to the rest of the application.

691
00:30:00,210 --> 00:30:03,420
You can have a user repository
where you pass a user ID,

692
00:30:03,420 --> 00:30:06,000
and it returns your
LiveData of users.

693
00:30:06,000 --> 00:30:07,650
How it gets the data?

694
00:30:07,650 --> 00:30:10,260
You don't care, it's
the repository's job.

695
00:30:10,260 --> 00:30:11,280
So how does it do that?

696
00:30:11,280 --> 00:30:12,420
It talks to the--

697
00:30:12,420 --> 00:30:15,920
fetching, syncing,
looking at database,

698
00:30:15,920 --> 00:30:17,990
or talking to your
retrofit back end.

699
00:30:17,990 --> 00:30:20,770
It's the repository's job.

700
00:30:20,770 --> 00:30:23,100
And last but not least,
we have our data sources,

701
00:30:23,100 --> 00:30:25,020
like your REST API client.

702
00:30:25,020 --> 00:30:28,470
You might be using Retrofit,
or you have SQLite storage.

703
00:30:28,470 --> 00:30:30,500
You might be using Room,
or you might be using

704
00:30:30,500 --> 00:30:32,460
GRAM, doesn't really matter.

705
00:30:32,460 --> 00:30:34,920
Or you might be talking
to other content providers

706
00:30:34,920 --> 00:30:36,390
from other processes.

707
00:30:36,390 --> 00:30:39,090
These are things we
call data sources.

708
00:30:39,090 --> 00:30:41,940
And we think that
all of these layers

709
00:30:41,940 --> 00:30:43,830
can discover each
other to create

710
00:30:43,830 --> 00:30:45,630
dependency checks
to the system which

711
00:30:45,630 --> 00:30:47,370
we'll command using Dagger.

712
00:30:47,370 --> 00:30:49,800
But we also realize that
understanding dependency

713
00:30:49,800 --> 00:30:51,810
situation is not very trivial.

714
00:30:51,810 --> 00:30:55,560
It's a more complex topic, and
sometimes might be an overkill.

715
00:30:55,560 --> 00:30:57,750
And you could also
use a service locator

716
00:30:57,750 --> 00:31:01,560
if you feel more
comfortable with it.

717
00:31:01,560 --> 00:31:04,050
So let's go back to--

718
00:31:04,050 --> 00:31:06,700
go through a concrete example.

719
00:31:06,700 --> 00:31:10,110
Let's say we have a UI
that shows a user profile,

720
00:31:10,110 --> 00:31:12,380
and we have the
data sources which--

721
00:31:12,380 --> 00:31:16,080
we save it to database, we also
can get it from the network.

722
00:31:16,080 --> 00:31:18,210
How do we connect
these two things?

723
00:31:18,210 --> 00:31:21,240
Well, we said we first
need a user repository.

724
00:31:21,240 --> 00:31:23,880
User repository knows it
should check the database.

725
00:31:23,880 --> 00:31:25,680
It's not there,
make a web request.

726
00:31:25,680 --> 00:31:28,500
Or meanwhile, also try
to run the database.

727
00:31:28,500 --> 00:31:30,750
It doesn't matter
how it does it,

728
00:31:30,750 --> 00:31:32,820
but it knows how to
create a LiveData

729
00:31:32,820 --> 00:31:36,780
of a user or an
observable, doesn't matter.

730
00:31:36,780 --> 00:31:38,430
And then we need the
ViewModel, right,

731
00:31:38,430 --> 00:31:41,670
because the data for the
UI lives in the ViewModel.

732
00:31:41,670 --> 00:31:44,220
So we create this
ProfileViewModel,

733
00:31:44,220 --> 00:31:48,030
which talks to the repository
to get this information.

734
00:31:48,030 --> 00:31:50,850
And then the actual
fragment gets the data

735
00:31:50,850 --> 00:31:54,450
from the view model so that
if the fragment comes back,

736
00:31:54,450 --> 00:31:57,270
the LiveData will be there
in the ProfileViewModel.

737
00:31:57,270 --> 00:32:00,070
But if the fragment
disappears completely,

738
00:32:00,070 --> 00:32:01,680
we will get rid
of the ViewModel,

739
00:32:01,680 --> 00:32:05,240
and the data can be
garbage collected.

740
00:32:05,240 --> 00:32:07,100
Now, all this
abstraction we made,

741
00:32:07,100 --> 00:32:10,640
if you notice, every single
component only talks to the one

742
00:32:10,640 --> 00:32:14,520
right below it, which is--
helps to scale your application.

743
00:32:14,520 --> 00:32:16,340
It also has a
great side benefit,

744
00:32:16,340 --> 00:32:18,260
which is called testing.

745
00:32:18,260 --> 00:32:19,230
You're testing, right?

746
00:32:19,230 --> 00:32:24,500


747
00:32:24,500 --> 00:32:26,210
So let's say you
want to test your UI.

748
00:32:26,210 --> 00:32:27,880
Now, people say UI
testing is hard.

749
00:32:27,880 --> 00:32:30,990
UI testing is--
yes, it's harder.

750
00:32:30,990 --> 00:32:33,320
But it's usually hard because
you put all of your code

751
00:32:33,320 --> 00:32:35,290
into that activity.

752
00:32:35,290 --> 00:32:38,630
Now, we said, put most
of it into the ViewModel,

753
00:32:38,630 --> 00:32:41,510
and you know that UI only
talks to the ViewModel,

754
00:32:41,510 --> 00:32:43,520
so you can get rid
of the other two.

755
00:32:43,520 --> 00:32:47,170
You only need to create a fake
ViewModel to test your UI.

756
00:32:47,170 --> 00:32:50,900
Testing your UI become super,
super easy with Espresso.

757
00:32:50,900 --> 00:32:52,880
And we have a
sample app on GitHub

758
00:32:52,880 --> 00:32:56,346
that you can check
out with [INAUDIBLE].

759
00:32:56,346 --> 00:32:58,220
And the same thing as
well as for ViewModels.

760
00:32:58,220 --> 00:32:59,660
If you want to
test the ViewModel,

761
00:32:59,660 --> 00:33:02,330
you know it's only talks
to the repositories.

762
00:33:02,330 --> 00:33:05,860
You replace it with a mock
respository, and it works.

763
00:33:05,860 --> 00:33:08,570
And you can even
test your ViewModels

764
00:33:08,570 --> 00:33:11,150
on your host machine, on JVM.

765
00:33:11,150 --> 00:33:12,780
And last but not
least, you can test

766
00:33:12,780 --> 00:33:14,030
the respository the same way.

767
00:33:14,030 --> 00:33:16,040
You just mock the data sources.

768
00:33:16,040 --> 00:33:21,000
You can easily test your
repositories as JUnit test.

769
00:33:21,000 --> 00:33:23,060
Now, I know this has been
a lot of information.

770
00:33:23,060 --> 00:33:26,420
We have two sessions tomorrow,
and also documentation.

771
00:33:26,420 --> 00:33:29,630
But now I want to call
our product manager lUKAS

772
00:33:29,630 --> 00:33:32,646
to talk about what to do next.

773
00:33:32,646 --> 00:33:35,574
[APPLAUSE]

774
00:33:35,574 --> 00:33:41,425


775
00:33:41,425 --> 00:33:42,800
LUKAS BERGSTROM:
Like Yigit said,

776
00:33:42,800 --> 00:33:44,870
we just covered a lot of ground.

777
00:33:44,870 --> 00:33:46,820
And actually, we glossed
over a lot of detail

778
00:33:46,820 --> 00:33:48,080
while we did that.

779
00:33:48,080 --> 00:33:50,420
But luckily, you don't
have to remember everything

780
00:33:50,420 --> 00:33:51,950
that you just heard.

781
00:33:51,950 --> 00:33:56,180
We have a lot of material
for you to check out

782
00:33:56,180 --> 00:33:58,910
at developer.android.com/arch.

783
00:33:58,910 --> 00:34:03,305
And that link should start
working in 21 minutes.

784
00:34:03,305 --> 00:34:06,260


785
00:34:06,260 --> 00:34:07,790
We wanted to give
you guys a chance

786
00:34:07,790 --> 00:34:10,219
to kind of blog and tweet
about this before anybody else.

787
00:34:10,219 --> 00:34:13,190
So that's why we held it back.

788
00:34:13,190 --> 00:34:15,560
So yeah, we made having
good documentation

789
00:34:15,560 --> 00:34:18,469
and samples a priority from
the beginning of this project,

790
00:34:18,469 --> 00:34:22,310
since providing good guidance is
really one of the major goals.

791
00:34:22,310 --> 00:34:24,800
So you're going to find
in-depth documentation that's

792
00:34:24,800 --> 00:34:27,337
written from the perspective
of an app developer.

793
00:34:27,337 --> 00:34:29,420
You're going to find really
meaty sample apps that

794
00:34:29,420 --> 00:34:31,280
show how to build a real app.

795
00:34:31,280 --> 00:34:34,650
And just as an example of
how much work went into this,

796
00:34:34,650 --> 00:34:36,139
we have a GitHub
browser sample app

797
00:34:36,139 --> 00:34:39,440
that probably has better test
coverage than many real world

798
00:34:39,440 --> 00:34:42,170
apps, written by that guy.

799
00:34:42,170 --> 00:34:44,820


800
00:34:44,820 --> 00:34:47,420
And of course, we have the
guide to app architecture,

801
00:34:47,420 --> 00:34:50,929
which internally, we called the
Opinionated Guide for a while.

802
00:34:50,929 --> 00:34:53,210
And we think that
label still applies.

803
00:34:53,210 --> 00:34:55,639
But even if you're not
planning to use our recommended

804
00:34:55,639 --> 00:34:58,580
architecture, we think people
should check out the guide.

805
00:34:58,580 --> 00:35:04,010
It has principles that we think
apply to all apps on Android.

806
00:35:04,010 --> 00:35:07,760
And you're probably asking
yourself, do I not--

807
00:35:07,760 --> 00:35:09,830
what's the impact of
this going to be on me?

808
00:35:09,830 --> 00:35:13,160
Am I going to have to change the
way that I'm doing everything?

809
00:35:13,160 --> 00:35:15,315
You know, if you're
starting a new project,

810
00:35:15,315 --> 00:35:16,940
or if you have an
existing app, but you

811
00:35:16,940 --> 00:35:19,190
want to improve the
core architecture,

812
00:35:19,190 --> 00:35:22,100
then yeah, we recommend
taking a look at this stuff.

813
00:35:22,100 --> 00:35:24,050
It's still preview.

814
00:35:24,050 --> 00:35:26,790
We won't be hitting
1.0 for a few months,

815
00:35:26,790 --> 00:35:30,050
but we think it's definitely
ready for you guys

816
00:35:30,050 --> 00:35:32,460
to check out, and
use in projects.

817
00:35:32,460 --> 00:35:34,250
But if you're happy
with what you have,

818
00:35:34,250 --> 00:35:37,360
you don't need to
rewrite your app.

819
00:35:37,360 --> 00:35:39,530
So in the spirit of be
together, not the same,

820
00:35:39,530 --> 00:35:41,890
we're not dictating what
everyone has to use.

821
00:35:41,890 --> 00:35:44,590
If you're happy with your app
architecture, you can keep it.

822
00:35:44,590 --> 00:35:46,510
If you're happy with
your existing ORM,

823
00:35:46,510 --> 00:35:48,820
you don't have to use Room.

824
00:35:48,820 --> 00:35:51,910
Architecture components are
designed to work well together,

825
00:35:51,910 --> 00:35:55,780
but they do work
perfectly fine standalone.

826
00:35:55,780 --> 00:35:58,300
And mixing and matching
applies not only

827
00:35:58,300 --> 00:36:04,730
to architecture components,
but also third party libraries.

828
00:36:04,730 --> 00:36:11,760
So-- I'm waiting for
this slide to come up.

829
00:36:11,760 --> 00:36:14,389
So yeah, so you can
use what you have,

830
00:36:14,389 --> 00:36:16,680
and to start to integrate
architecture components where

831
00:36:16,680 --> 00:36:18,310
they make sense.

832
00:36:18,310 --> 00:36:21,000
So for example, if you're
happy with Rx Java,

833
00:36:21,000 --> 00:36:24,510
but you really like the
Lifecycle aware component stuff

834
00:36:24,510 --> 00:36:27,360
that Yigit just showed, so that
you have these self-sufficient

835
00:36:27,360 --> 00:36:31,590
components, you can use
LiveData together with Rx Java.

836
00:36:31,590 --> 00:36:34,800
So you can get all the
power of Rx Java operators,

837
00:36:34,800 --> 00:36:36,420
and now it's Lifecycle safe.

838
00:36:36,420 --> 00:36:39,510
So kind of the best
of both worlds.

839
00:36:39,510 --> 00:36:41,760
And we've got additional
integrations to come.

840
00:36:41,760 --> 00:36:45,890
We're definitely looking at
a lot of stuff internally

841
00:36:45,890 --> 00:36:48,480
that would be nice if
it were self-sufficient

842
00:36:48,480 --> 00:36:50,500
and Lifecycle aware.

843
00:36:50,500 --> 00:36:53,460
And if you're a
library developer,

844
00:36:53,460 --> 00:36:55,920
we really recommend
checking out Lifecycles

845
00:36:55,920 --> 00:36:57,690
and LifecycleObserver
because we think

846
00:36:57,690 --> 00:37:00,480
there is a really bright
future, and a lot of potential

847
00:37:00,480 --> 00:37:03,420
in making libraries and
components that are Lifecycle

848
00:37:03,420 --> 00:37:07,870
aware by default.
But before you go

849
00:37:07,870 --> 00:37:11,110
do that, we have a lot more
for you at I/O this year.

850
00:37:11,110 --> 00:37:15,310
We have two more talks,
one on Lifecycles

851
00:37:15,310 --> 00:37:18,280
that's even more in-depth than
what we just showed tomorrow

852
00:37:18,280 --> 00:37:20,020
morning.

853
00:37:20,020 --> 00:37:24,040
We have another one on
Room and Persistence,

854
00:37:24,040 --> 00:37:25,480
and going a little
bit beyond Room

855
00:37:25,480 --> 00:37:27,790
starting at 12:30 tomorrow.

856
00:37:27,790 --> 00:37:31,950
And we'll have people who are
well-versed in architecture

857
00:37:31,950 --> 00:37:36,740
components in the
sandbox for all of I/O.

858
00:37:36,740 --> 00:37:41,600
And we also have codelabs,
which we're pretty happy with.

859
00:37:41,600 --> 00:37:43,890
And there's more to come.

860
00:37:43,890 --> 00:37:46,100
So we think we've just
scratched the surface of ways

861
00:37:46,100 --> 00:37:48,260
that we can improve the
experience of using Android

862
00:37:48,260 --> 00:37:51,320
Frameworks, and we're looking
at applying this approach

863
00:37:51,320 --> 00:37:53,310
in other areas as well.

864
00:37:53,310 --> 00:37:54,980
So some things
already in the works.

865
00:37:54,980 --> 00:37:58,310
And we're also interested in
hearing from you on what else

866
00:37:58,310 --> 00:37:59,720
you'd like to see.

867
00:37:59,720 --> 00:38:04,010
So come by, talk to us, tell us
what you like, what you don't.

868
00:38:04,010 --> 00:38:06,800
And stay tuned, because we're
really excited about the future

869
00:38:06,800 --> 00:38:08,570
of Android development.

870
00:38:08,570 --> 00:38:09,310
Thank you.

871
00:38:09,310 --> 00:38:11,460
[APPLAUSE]

872
00:38:11,460 --> 00:00:00,000


1
00:00:00,000 --> 00:00:05,189
[Музыка]

2
00:00:05,189 --> 00:00:05,980
MIKE CLERON: Привет!

3
00:00:05,980 --> 00:00:07,080
Я Майк Клерон.

4
00:00:07,080 --> 00:00:08,650
Я из Android team.

5
00:00:08,650 --> 00:00:14,120
Я разрабатываю UI фреймворк
и UI средства разработки [toolkit]

6
00:00:14,120 --> 00:00:17,650
Сегодня мы будем говорить
о многих деталях

7
00:00:17,650 --> 00:00:21,790
и о некоторых больших изменениях в подходах,
которые мы рекомендуем

8
00:00:21,790 --> 00:00:23,710
при проектировании приложений для Android.

9
00:00:23,710 --> 00:00:26,110
Но прежде чем мы погрузимся
в детали,

10
00:00:26,110 --> 00:00:28,510
я думаю, что будет полезно
сделать шаг в сторону,

11
00:00:28,510 --> 00:00:31,960
и поговорить о том,
откуда мы пришли

12
00:00:31,960 --> 00:00:34,730
и куда мы идем.

13
00:00:34,730 --> 00:00:36,100
Давайте начнем.

14
00:00:36,100 --> 00:00:39,010
Итак, Android
всегда основывался на

15
00:00:39,010 --> 00:00:41,230
на нескольких прочных принципах

16
00:00:41,230 --> 00:00:43,330
Не удивительно, они
были лучше всего выражены

17
00:00:43,330 --> 00:00:44,860
Дианой Хакборн.

18
00:00:44,860 --> 00:00:46,600
Она из тех, кто
реально проектировали

19
00:00:46,600 --> 00:00:48,880
большую часть Android фреймворков.

20
00:00:48,880 --> 00:00:51,160
Она написала пост об этом
несколько месяцев назад,

21
00:00:51,160 --> 00:00:54,310
и у меня есть некоторые
выдержки оттуда.

22
00:00:54,310 --> 00:00:56,230
Если вы посмотрите на примитивы
ядра Android --

23
00:00:56,230 --> 00:01:00,100
Activity, BroadcastReceiver,
Service, ContentProvider,

24
00:01:00,100 --> 00:01:03,880
у вас есть основание думать, что
они составляют каркас

25
00:01:03,880 --> 00:01:05,012
приложения (framework).

26
00:01:05,012 --> 00:01:06,970
Но это не верный способ
думать об этом.

27
00:01:06,970 --> 00:01:10,120
Эти классы фактически
контракты

28
00:01:10,120 --> 00:01:14,910
между приложением
и операционной системой (ОС).

29
00:01:14,910 --> 00:01:16,950
Они представляют собой минимальное
количество информации

30
00:01:16,950 --> 00:01:20,790
необходимое, чтобы ОС знала,
что происходит внутри вашего приложения

31
00:01:20,790 --> 00:01:23,220
т.о. мы можем управлять этим правильно.


32
00:01:23,220 --> 00:01:27,060
Итак, для примера, если ваше
приложение работает в фоне,

33
00:01:27,060 --> 00:01:29,600
но также предоставляет данные
другому приложению

34
00:01:29,600 --> 00:01:32,492
через ContentProvider,
то ОС должна об этом знать.

35
00:01:32,492 --> 00:01:34,950
И мы должны знать, что случайно
не убьем его.

36
00:01:34,950 --> 00:01:37,500
ContentProvider это механизм
который говорит нам,

37
00:01:37,500 --> 00:01:39,990
что мы должны держать вас живыми.

38
00:01:39,990 --> 00:01:41,970
Итак, мы думаем об
этих основных классах

39
00:01:41,970 --> 00:01:44,790
как действительно существующих
подобно фундаментальным законам физики

40
00:01:44,790 --> 00:01:47,520
для Android. Тогда
иллюстрация.

41
00:01:47,520 --> 00:01:49,920
Это обложка книги,
где впервые

42
00:01:49,920 --> 00:01:52,170
Исаак Ньютон
описал

43
00:01:52,170 --> 00:01:53,430
фундаментальные законы движения.

44
00:01:53,430 --> 00:01:56,620


45
00:01:56,620 --> 00:01:59,580
Теперь, фундаментальные законы
это отличная вещь.

46
00:01:59,580 --> 00:02:01,560
Я использую условные обозначения
Когда говорю об этом.

47
00:02:01,560 --> 00:02:04,530
Я говорю "У Android хорошие кости",
даже если люди смотрят на меня

48
00:02:04,530 --> 00:02:06,780
с усмешкой после этого.

49
00:02:06,780 --> 00:02:09,960
Но что я имею в виду, когда
говорю, что Android это Android

50
00:02:09,960 --> 00:02:13,650
он небольшой, стабильный,
имеет связанный набор

51
00:02:13,650 --> 00:02:15,150
примитивов ядра.

52
00:02:15,150 --> 00:02:18,390
И это позволяет иметь
общую программную модель Android

53
00:02:18,390 --> 00:02:20,940
на очень широком диапазоне
различных устройств

54
00:02:20,940 --> 00:02:24,750
от носимых устройств, телефонов,
планшетов

55
00:02:24,750 --> 00:02:27,870
до ТВ, автомобилей и т.д.

56
00:02:27,870 --> 00:02:30,210
И эта же модель дает
разработчикам приложений

57
00:02:30,210 --> 00:02:32,310
свободу выбора
любого фреймворка

58
00:02:32,310 --> 00:02:34,170
какой они хотят использовать
для своего приложения

59
00:02:34,170 --> 00:02:36,010
для их внутренней структуры.

60
00:02:36,010 --> 00:02:38,070
Это означает, что нам
в команде Android

61
00:02:38,070 --> 00:02:41,250
не следует заниматься дебатами
что лучше: MVC

62
00:02:41,250 --> 00:02:45,540
или MVP, или что
MVP лучше чем [? MVVBM. ?]

63
00:02:45,540 --> 00:02:49,260
Вы, ребята, выбирайте что угодно
что имеет смысл для вас.

64
00:02:49,260 --> 00:02:52,680
И это звучит хорошо для нас,
находящихся

65
00:02:52,680 --> 00:02:55,921
в разработке ОС, как я

66
00:02:55,921 --> 00:02:57,420
Но если вы разработчик
приложений

67
00:02:57,420 --> 00:03:01,110
скажем, каждый из вас.
Что ж, тогда

68
00:03:01,110 --> 00:03:03,120
это только одна глава
в этой истории.

69
00:03:03,120 --> 00:03:04,890
И причина в том,
что хотя

70
00:03:04,890 --> 00:03:08,190
строгие фундаментальные основы
и свобода выбора [реализации]

71
00:03:08,190 --> 00:03:12,000
это хорошие вещи, мы знаем, что
в повседневной работе [этого мало]-

72
00:03:12,000 --> 00:03:16,730
и мы знаем это потому, что
вы говорите, что хотите большего от нас.

73
00:03:16,730 --> 00:03:19,690
Так что я буду немного надоедать
моей аналогией.

74
00:03:19,690 --> 00:03:22,810
Мы все можем оценить
простую элегантность законов Ньютона

75
00:03:22,810 --> 00:03:27,725
о движении, но если вы собираетесь
высадить марсоход на Марс,

76
00:03:27,725 --> 00:03:29,350
вам не захочется, приходить
на работу каждый день и

77
00:03:29,350 --> 00:03:31,810
и начинать с того, что сила равна
масса на ускорение, и получить все

78
00:03:31,810 --> 00:03:35,230
из оснований классической механики Ньютона.

79
00:03:35,230 --> 00:03:37,780
Итак, мы поговорили с разработчиками
с обеих сторон, внутри

80
00:03:37,780 --> 00:03:41,140
и вне Google, и при этом
внимательно изучали

81
00:03:41,140 --> 00:03:42,830
опыт разработки приложений.

82
00:03:42,830 --> 00:03:45,230
И нам удалось понять
несколько вещей.

83
00:03:45,230 --> 00:03:47,770
Первое, у нас есть вершины
и есть долины.

84
00:03:47,770 --> 00:03:51,550
Некоторые аспекты разработки
прекрасно обслуживаются нашими API

85
00:03:51,550 --> 00:03:52,570
другие - хуже.

86
00:03:52,570 --> 00:03:56,470
Например, мы думаем, что
RecyclerView это лучшая вершина

87
00:03:56,470 --> 00:03:57,830
из этого спектра.

88
00:03:57,830 --> 00:04:02,020
С RecyclerView, мы не говорим:
эй, мы даем вам события,

89
00:04:02,020 --> 00:04:03,810
и вы можете рисовать вещи.

90
00:04:03,810 --> 00:04:07,600
И у вас есть тьюринг-полный язык,
так что удачи

91
00:04:07,600 --> 00:04:09,550
со всем остальным!

92
00:04:09,550 --> 00:04:12,640
С другой стороны,
возможно жизненные циклы

93
00:04:12,640 --> 00:04:16,510
Activity и Fragment принадлежат
к темным впадинам

94
00:04:16,510 --> 00:04:18,730
потому что там, я
думаю, оставлено действительно

95
00:04:18,730 --> 00:04:21,790
слишком много упражнений
для читателя [необходимо много читать].

96
00:04:21,790 --> 00:04:24,730
И мы хотим исправить это.

97
00:04:24,730 --> 00:04:27,250
Итак, мы думаем,
что хорошее решение имеет

98
00:04:27,250 --> 00:04:29,930
ключевые свойства.

99
00:04:29,930 --> 00:04:32,194
Во-первых, мы обязаны находить
правильные проблемы.

100
00:04:32,194 --> 00:04:33,860
И это будет
непрерывным усилием --

101
00:04:33,860 --> 00:04:36,320
так же как и с нашей стороны
для нас на Android.

102
00:04:36,320 --> 00:04:38,410
Но для первого сокращения,
мы хотим убедиться,

103
00:04:38,410 --> 00:04:39,910
что мы будем решать
проблемы, с которыми

104
00:04:39,910 --> 00:04:42,040
сталкивается каждый разработчик.
Те, которые трудно решить

105
00:04:42,040 --> 00:04:45,040
прямо сейчас. Опять же,

106
00:04:45,040 --> 00:04:47,574
жизненный цикл приложения -
на самом деле хороший пример.

107
00:04:47,574 --> 00:04:49,240
Если вы не получите это право
[управлять циклом] в своем приложении,

108
00:04:49,240 --> 00:04:51,236
на нем ничего
не будет работать.

109
00:04:51,236 --> 00:04:53,110
Это верно для вашего
приложения, но так же

110
00:04:53,110 --> 00:04:55,026
верно для фреймворков,
которые мы пытаемся создавать.

111
00:04:55,026 --> 00:04:58,420
Мы должны получить это право
до того как можем сделать что-нибудь еще.

112
00:04:58,420 --> 00:05:00,370
Второе, мы должны хорошо
координировать свою работу с другими.

113
00:05:00,370 --> 00:05:02,830
Мы знаем, что вы здорово
вкладываетесь в существующие

114
00:05:02,830 --> 00:05:05,196
модели программирования, и мы
не можем создать модель,

115
00:05:05,196 --> 00:05:06,820
где сразу скажем
вам, чтобы вы,

116
00:05:06,820 --> 00:05:08,940
бросили все старое
и начали сначала.

117
00:05:08,940 --> 00:05:12,070
Итак, мы стараемся создать API,
на которое вы не потратите много

118
00:05:12,070 --> 00:05:15,580
времени, и также которое
хорошо взаимодействует

119
00:05:15,580 --> 00:05:19,710
с другими библиотеками
и другими фреймворками.

120
00:05:19,710 --> 00:05:22,054
В-третьих, мы хотим быть
более настойчивыми.

121
00:05:22,054 --> 00:05:23,970
Мы собираемся занять более
сильную и четкую позицию

122
00:05:23,970 --> 00:05:26,000
о том, каким должен быть
правильный путь развития Android,

123
00:05:26,000 --> 00:05:27,100
По крайней мере, как мы это видим.

124
00:05:27,100 --> 00:05:29,100
Теперь, это все еще необязательно.

125
00:05:29,100 --> 00:05:31,330
И если у вас уже есть,
то, что работает для вас,

126
00:05:31,330 --> 00:05:33,030
то это здорово.

127
00:05:33,030 --> 00:05:36,210
Но разработчики говорят нам,
что хотели бы большей ясности о том,

128
00:05:36,210 --> 00:05:38,590
как следует строить приложения.
И к слову

129
00:05:38,590 --> 00:05:40,770
мы не меняем "законов
физики" [core Android] здесь,

130
00:05:40,770 --> 00:05:43,860
мы просто меняем конструкции
более высокого уровня.

131
00:05:43,860 --> 00:05:46,620
Потому что сила будет равна масса
умножить на ускорение несмотря на то

132
00:05:46,620 --> 00:05:49,860
верите ли вы в это или нет.

133
00:05:49,860 --> 00:05:52,140
Следующее, необходимо масштабировать.

134
00:05:52,140 --> 00:05:54,420
Нам нужны решения, которые
обладают индустриальной мощью

135
00:05:54,420 --> 00:05:56,760
и могут масштабироваться
под реальные мировые требования

136
00:05:56,760 --> 00:05:58,474
реальных приложений.

137
00:05:58,474 --> 00:06:01,140
Мы не хотим создавать что-то,
что хорошо работает для Hello World,

138
00:06:01,140 --> 00:06:03,181
но сдает позиции сразу же
при первом использовании,

139
00:06:03,181 --> 00:06:07,620
когда сталкивается с суровой,
сложной реальностью.

140
00:06:07,620 --> 00:06:09,410
И наконец, поддержка и обогащение [версий Android].

141
00:06:09,410 --> 00:06:11,310
Для [решения] этой проблемы,
для упрощения

142
00:06:11,310 --> 00:06:13,830
написания приложений Android
правильным способом --

143
00:06:13,830 --> 00:06:15,690
мы думаем,
что будет правильным

144
00:06:15,690 --> 00:06:18,390
использовать библиотеки наподобие
Support Lib где это только возможно,

145
00:06:18,390 --> 00:06:21,150
а не добавлять новые
API на платформу,

146
00:06:21,150 --> 00:06:24,030
потому что таким образом мы
сможем обогатить старые версии ОС

147
00:06:24,030 --> 00:06:26,745
так же.

148
00:06:26,745 --> 00:06:29,370
OK, это то на чем мы основываемся,
что, что мы пытаемся осуществить,

149
00:06:29,370 --> 00:06:30,440
и почему мы находимся здесь.

150
00:06:30,440 --> 00:06:33,309
Теперь мы бы хотели представить
Yigit, инженера средств разработки.

151
00:06:33,309 --> 00:06:35,600
И он собирается рассказать вам
как мы это

152
00:06:35,600 --> 00:06:36,860
осуществляли на практике. Спасибо.

153
00:06:36,860 --> 00:06:37,290
[АПЛОДИСМЕНТЫ]

154
00:06:37,290 --> 00:06:38,248
YIGIT BOYAR: Хорошо.

155
00:06:38,248 --> 00:06:39,322
Спасибо, Frank.

156
00:06:39,322 --> 00:06:43,610


157
00:06:43,610 --> 00:06:44,410
Привет всем.

158
00:06:44,410 --> 00:06:46,930
Итак, это было то, на чем мы основываемся.

159
00:06:46,930 --> 00:06:49,050
К чему мы идем сегодня?

160
00:06:49,050 --> 00:06:51,210
Первая вещь
к которой мы идем

161
00:06:51,210 --> 00:06:55,230
это руководство по архитектуре
на developer Android com.

162
00:06:55,230 --> 00:06:58,440
На протяжении многих лет вы
спрашивали наше мнение,

163
00:06:58,440 --> 00:07:02,220
как по-нашему приложение
должно быть построено?

164
00:07:02,220 --> 00:07:03,900
И это и есть это руководство.

165
00:07:03,900 --> 00:07:06,270
И мы считаем, что
оно достаточно хорошо,

166
00:07:06,270 --> 00:07:08,730
и покрывает большинство
видов приложений.

167
00:07:08,730 --> 00:07:10,890
Но даже если вы имеете
свою архитектуру

168
00:07:10,890 --> 00:07:14,040
которая удобна для вас,
вы можете сохранять ее.

169
00:07:14,040 --> 00:07:18,300
Но вы можете попробовать узнать
что-то новое из этого руководства

170
00:07:18,300 --> 00:07:20,910
Во-вторых, мы движемся к созданию
нового набора библиотек,

171
00:07:20,910 --> 00:07:23,290
которые мы называем
архитектурные компоненты.

172
00:07:23,290 --> 00:07:24,900
Это более фундаментальные
компоненты [строительные блоки]

173
00:07:24,900 --> 00:07:28,440
на которых вы можете
основывать ваше приложение.

174
00:07:28,440 --> 00:07:29,760
Первая вещь - жизненный цикл.

175
00:07:29,760 --> 00:07:33,000
Это самая частая жалоба,
которую мы получаем от разработчиков.

176
00:07:33,000 --> 00:07:35,610
Жизненный цикл сложен,
Жизненный цикл сложен.

177
00:07:35,610 --> 00:07:38,020
И мы сказали "ОК", нам
следует решить эту проблему.

178
00:07:38,020 --> 00:07:41,850
И первый шаг для этого,
это новый набор компонентов.

179
00:07:41,850 --> 00:07:44,070
Второе - это учитывающие
жизненный цикл Observables,

180
00:07:44,070 --> 00:07:46,860
которые в деталях будут рассмотрены
позже, но базово это

181
00:07:46,860 --> 00:07:51,730
сделать что-то, базируясь
на жизненном цикле.

182
00:07:51,730 --> 00:07:54,810
В-третьих, мы собираемся представить
легковесные ViewModel, которые

183
00:07:54,810 --> 00:07:58,020
помогут вывести
ваш код

184
00:07:58,020 --> 00:08:00,150
наружу из ваших
Activities и Fragments,

185
00:08:00,150 --> 00:08:03,550
и поместить его где-нибудь еще,
где вы сможете легко протестировать его.

186
00:08:03,550 --> 00:08:06,630
И последнее, но не менее важное,
мы собираемся представить новый объект

187
00:08:06,630 --> 00:08:10,290
mapping library для SQLite.

188
00:08:10,290 --> 00:08:15,248
И все это доступно для вас
сегодня на Maven Google com.

189
00:08:15,248 --> 00:08:24,290
[АПЛОДИСМЕНТЫ]

190
00:08:24,290 --> 00:08:25,790
Давайте поговорим о жизненных циклах.

191
00:08:25,790 --> 00:08:27,830
Итак, что же сложного
в жизненных циклах?

192
00:08:27,830 --> 00:08:29,970
Почему мы слышим так много
жалоб об этом?

193
00:08:29,970 --> 00:08:31,510
Давайте перейдем к примеру.

194
00:08:31,510 --> 00:08:33,440
Предположим, что у нас есть
Activity где мы

195
00:08:33,440 --> 00:08:36,591
хотим выводить местоположение
устройства на экран.

196
00:08:36,591 --> 00:08:38,090
Итак, вы попробуете сделать
что-то вроде этого.

197
00:08:38,090 --> 00:08:41,280
Вы создадите LocationListener
в методе onCreate(),

198
00:08:41,280 --> 00:08:43,250
вам нужно будет инициализировать
его контекстом [Context],

199
00:08:43,250 --> 00:08:46,520
и у вас будет обратный вызов [callback],
который вызывается всякий раз, когда

200
00:08:46,520 --> 00:08:48,800
локация меняется, и вы обновляете UI.

201
00:08:48,800 --> 00:08:51,230
Теперь, если вы когда-либо
писали приложение на Android,

202
00:08:51,230 --> 00:08:54,330
вы знаете, что этого
кода недостаточно.

203
00:08:54,330 --> 00:08:57,440
Вам также нужно пойти дальше и
переопределить onStart(), и затем

204
00:08:57,440 --> 00:09:01,880
дать команду начинать, и переопределить
onStop(), и дать команду остановиться.

205
00:09:01,880 --> 00:09:04,040
Вы всегда должны
таким образом присматривать

206
00:09:04,040 --> 00:09:05,510
за этими компонентами.

207
00:09:05,510 --> 00:09:06,840
Но это приемлемо.

208
00:09:06,840 --> 00:09:09,680
Это простой пример,
это выглядит хорошо.

209
00:09:09,680 --> 00:09:11,750
Но тогда появляется ваш
Product Manager и говорит,

210
00:09:11,750 --> 00:09:12,560
"О, ды та знаешь что?"

211
00:09:12,560 --> 00:09:16,160
"Нам необходимо проверить сначала
настройки пользователя перед разрешением--

212
00:09:16,160 --> 00:09:17,710
спрашивать о местоположении."

213
00:09:17,710 --> 00:09:22,160
Тогда вам разработчик скажет "OK"
конечно, "Это просто изменить."

214
00:09:22,160 --> 00:09:25,570
"Я изменю этот метод, который
будет вызывать утилиту,

215
00:09:25,570 --> 00:09:27,980
которая, вероятно, сделает
запрос к веб-сервису

216
00:09:27,980 --> 00:09:29,900
и проверить настройки пользователя.

217
00:09:29,900 --> 00:09:32,030
И тогда, если
пользователь зарегистрирован,

218
00:09:32,030 --> 00:09:34,160
мы запустим наш
LocationListener."

219
00:09:34,160 --> 00:09:37,010
Это похоже на
очень простое изменение,

220
00:09:37,010 --> 00:09:39,440
вы подумаете, что это могло бы
сработать, но давайте посмотрим,

221
00:09:39,440 --> 00:09:42,440
что происходит в жизненном цикле
этой Activity.

222
00:09:42,440 --> 00:09:43,990
Итак наша Activity была создана.

223
00:09:43,990 --> 00:09:49,526
Мы говорим "OK", запускаем проверку
зарегистрирован ли пользователь.

224
00:09:49,526 --> 00:09:52,370
Но вдруг, пользователь захотел
повернуть устройство.

225
00:09:52,370 --> 00:09:54,930
И поворот означает
смену конфигурации,

226
00:09:54,930 --> 00:09:58,430
что означает, что Android начнет
пересоздавать Activity.

227
00:09:58,430 --> 00:10:00,200
Итак в onStop(), мы
узнаем об этом,

228
00:10:00,200 --> 00:10:03,292
и мы скажем "OK"
location manager остановился.

229
00:10:03,292 --> 00:10:05,780
И затем появляется новая
Activity, и она также

230
00:10:05,780 --> 00:10:07,430
проходит через то же самое.

231
00:10:07,430 --> 00:10:10,280
Выглядит хорошо, исключая,
как вы помните, наш запрос,

232
00:10:10,280 --> 00:10:12,140
который мы сделали до того.

233
00:10:12,140 --> 00:10:15,400
Это маленькое изменение [поворот],
и затем запрос возвращает ответ.

234
00:10:15,400 --> 00:10:17,110
"Эй, пользователь зарегистрирован".

235
00:10:17,110 --> 00:10:18,080
И что мы тогда делаем?

236
00:10:18,080 --> 00:10:20,790
Мы скажем "OK, стартуй!".

237
00:10:20,790 --> 00:10:22,250
И вы осознаете [НЕРАЗБОРЧИВО]?

238
00:10:22,250 --> 00:10:26,510
Мы вызываем onStart() после
вызова onStop(), это означает,

239
00:10:26,510 --> 00:10:28,700
наша Activity будет жить вечно.

240
00:10:28,700 --> 00:10:31,130
Мы будем наблюдать это
местоположение вечно,

241
00:10:31,130 --> 00:10:32,257
пока батарея не разрядится.

242
00:10:32,257 --> 00:10:33,215
Мы опечалим наших пользователей.

243
00:10:33,215 --> 00:10:37,078


244
00:10:37,078 --> 00:10:38,600
Знакомая ситуация, не так ли?

245
00:10:38,600 --> 00:10:40,220
Мы хотим избавиться от этого.

246
00:10:40,220 --> 00:10:41,840
Мы хотим положить этому конец.

247
00:10:41,840 --> 00:10:43,950
Итак, мы говорим "OK", нам
нужно признать -

248
00:10:43,950 --> 00:10:46,670
как упоминал Майк,
мы не можем изменить законы.

249
00:10:46,670 --> 00:10:49,670
Но мы можем поступить проще:
иметь дело с вещами.

250
00:10:49,670 --> 00:10:52,430
Поэтому мы решили ввести
новый интерфейс называемый

251
00:10:52,430 --> 00:10:53,970
LifecycleOwner.

252
00:10:53,970 --> 00:10:55,970
Эта вещь идет вместе с
жизненным циклом.

253
00:10:55,970 --> 00:10:58,400
Если у вас Activity, или
ваш Fragment - или, возможно,

254
00:10:58,400 --> 00:11:02,270
ваш собственный UI фреймворк,
независимо от того, что у вас есть,

255
00:11:02,270 --> 00:11:05,570
это можно представить, как LifecycleOwner.

256
00:11:05,570 --> 00:11:08,780
И у нас есть [наблюдатели]
LifecycleObservers,

257
00:11:08,780 --> 00:11:11,180
цель которых заботиться
о жизненном цикле.

258
00:11:11,180 --> 00:11:13,310
Как и в
LocationListener у нас было,

259
00:11:13,310 --> 00:11:16,580
он заботится о жизненном цикле,
хочет остановить себя

260
00:11:16,580 --> 00:11:18,680
Если жизненный цикл не активен.

261
00:11:18,680 --> 00:11:21,130
Итак, мы сказали "OK,
мы признаем это.

262
00:11:21,130 --> 00:11:23,600
И у нас есть
LifecycleObservers."

263
00:11:23,600 --> 00:11:26,090
Мы пройдем через код
в нашей Acivity.

264
00:11:26,090 --> 00:11:30,080
Сейчас мы наследуем нашу Activity
от класса LifecycleActivity.

265
00:11:30,080 --> 00:11:33,320
Это лишь временный класс
пока эти компоненты дойдут

266
00:11:33,320 --> 00:11:34,410
до версии 1.0.

267
00:11:34,410 --> 00:11:35,900
Затем все в
Support Library

268
00:11:35,900 --> 00:11:39,980
реализует интерфейс
LifecycleOwner.

269
00:11:39,980 --> 00:11:42,550
Внутри нашей Activity,
где мы инициализируем

270
00:11:42,550 --> 00:11:45,710
наш LocationListener,
мы собираемя сказать, что

271
00:11:45,710 --> 00:11:48,240
это наш жизненный цикл,
о котором мы заботимся.

272
00:11:48,240 --> 00:11:50,390
И это все, что мы делаем.

273
00:11:50,390 --> 00:11:54,410
Но поскольку это то же самое,
он вызывает обновление UI.

274
00:11:54,410 --> 00:11:57,020
Итак, как мы можем изменить
наш LocationListener

275
00:11:57,020 --> 00:12:00,890
используя преимущества
этого жизненного цикла?

276
00:12:00,890 --> 00:12:03,500
О, мы делаем тоже самое
для UserStatus также.

277
00:12:03,500 --> 00:12:06,240


278
00:12:06,240 --> 00:12:08,880
Итак, есть некоторые шаблоны
кода здесь, чтобы получить поля.

279
00:12:08,880 --> 00:12:10,950
Это на самом деле
не важно, но у нас есть

280
00:12:10,950 --> 00:12:14,850
этот метод, enable(), который вызывается,
если пользователь зарегистрирован.

281
00:12:14,850 --> 00:12:16,500
Внутри этого метода
мы теперь

282
00:12:16,500 --> 00:12:18,420
хотим начать
отслеживать местоположение

283
00:12:18,420 --> 00:12:21,360
только, если Activity запущена.

284
00:12:21,360 --> 00:12:23,040
Теперь вы можете сделать это.

285
00:12:23,040 --> 00:12:26,590
Вы можете узнать, какое ваше текущее
состояние, и это удивительно.

286
00:12:26,590 --> 00:12:29,370
У нас не было
такого API до сих пор.

287
00:12:29,370 --> 00:12:32,010
Ну, теперь вы можете это.

288
00:12:32,010 --> 00:12:34,110
Итак, хорошо, это было простое изменение.

289
00:12:34,110 --> 00:12:36,510
Но мы также получаем уведомление,
что мы зарегистрированы,

290
00:12:36,510 --> 00:12:38,710
когда Activity
будет не в активном состоянии,

291
00:12:38,710 --> 00:12:40,800
и пользователь
вернется к Activity.

292
00:12:40,800 --> 00:12:43,290
Теперь нам следует на самом деле
запустить LocationManager.

293
00:12:43,290 --> 00:12:46,290
Для этого мы хотим наблюдать за
жизненным циклом.

294
00:12:46,290 --> 00:12:48,690
Здесь мы имплементируем
этот интерфейс,

295
00:12:48,690 --> 00:12:50,670
который позволяет нам
использовать эти методы.

296
00:12:50,670 --> 00:12:52,710
Вы можете аннотировать эти
методы, говоря что,

297
00:12:52,710 --> 00:12:56,152
если ON_START
случился, вызывай этот метод.

298
00:12:56,152 --> 00:12:58,360
И новые компоненты будут
заботиться о вызовах.

299
00:12:58,360 --> 00:13:00,660
Итак, если вы теперь доступны,
то теперь вы начинаете,

300
00:13:00,660 --> 00:13:03,540
и если ON_STOP
вы отключаетесь.

301
00:13:03,540 --> 00:13:06,700
И последнее по порядку, но не по значимости,
Если Activity остановлено и уничтожено,

302
00:13:06,700 --> 00:13:09,220
вам ничего не нужно делать
с этой Activity

303
00:13:09,220 --> 00:13:11,796
Вы можете разрегистрироваться.

304
00:13:11,796 --> 00:13:13,920
Итак, вы тогда можете скать себе:
"Хорошо, вы просто

305
00:13:13,920 --> 00:13:16,710
перенесли эти ON_START, ON_STOP
методы из Activity

306
00:13:16,710 --> 00:13:18,450
в Location Manager.

307
00:13:18,450 --> 00:13:20,150
Почему это проще?"

308
00:13:20,150 --> 00:13:22,250
Это проще потому, что
эти методы

309
00:13:22,250 --> 00:13:23,610
находятся в правильном месте.

310
00:13:23,610 --> 00:13:27,690
И это LocationManager, который
заботиться о жизненном цикле.

311
00:13:27,690 --> 00:13:30,780
И это следует делать
без того, чтобы Activity

312
00:13:30,780 --> 00:13:32,460
нянчила сама себя.

313
00:13:32,460 --> 00:13:34,170
Я уверен, если вы посмотрите
в ваш код сегодня,

314
00:13:34,170 --> 00:13:37,260
в вашей Activity методы
ON_START, ON_STOP, будут занимать,

315
00:13:37,260 --> 00:13:38,730
не менее 20-30 строк кода.

316
00:13:38,730 --> 00:13:42,060
Мы хотим, чтобы они
занимали 0 строк кода.

317
00:13:42,060 --> 00:13:43,800
И если мы вернемся к Activity,
я хочу указать

318
00:13:43,800 --> 00:13:45,780
на кое-что -

319
00:13:45,780 --> 00:13:49,260
Смотрите, в onCreate(), мы
инициализируем эти компоненты.

320
00:13:49,260 --> 00:13:50,580
И это все, что мы делаем.

321
00:13:50,580 --> 00:13:53,230
Мы не переопределяем, мы
не пишем ON_STOP, ON_START,

322
00:13:53,230 --> 00:13:55,020
мы не переопределяем
никакие из этих сущностей,

323
00:13:55,020 --> 00:13:59,630
потому что LocationManager это компонент,
осведомленный о жизненном цикле

324
00:13:59,630 --> 00:14:01,875
теперь.

325
00:14:01,875 --> 00:14:03,990
Итак, это новая концепция,
которую мы хотим представить.

326
00:14:03,990 --> 00:14:08,130
Компонент осведомленный о жизненном
цикле, может получить его состояние,

327
00:14:08,130 --> 00:14:09,170
и поступать правильно таким образом.

328
00:14:09,170 --> 00:14:12,210
Он может заботиться о себе сам,
так что в вашей Activity

329
00:14:12,210 --> 00:14:15,120
вы можете просто инициализировать
это и забыть об этом.

330
00:14:15,120 --> 00:14:19,060
Вы можете не беспокоиться,
что это утечет от вас.

331
00:14:19,060 --> 00:14:22,480
Теперь, конечно, это было похоже
на перемещение комплекса

332
00:14:22,480 --> 00:14:24,520
из Activity в
LocationManager,

333
00:14:24,520 --> 00:14:27,310
и затем все еще нужно
иметь дело с жизненным циклом.

334
00:14:27,310 --> 00:14:29,190
Мы сказали "OK, чего мы хотим?"

335
00:14:29,190 --> 00:14:32,540
Это приятно суметь сделать это,
но мы хотим большего.

336
00:14:32,540 --> 00:14:35,230
Мы хотим больше удобства
для обработки этого общего случая.

337
00:14:35,230 --> 00:14:38,390
Довольно часто бывает, что
ваша Activity или Fragment

338
00:14:38,390 --> 00:14:41,830
наблюдают некоторые данные, и
всякий раз, когда данные меняются,

339
00:14:41,830 --> 00:14:43,300
они хотят обновить свое состояние.

340
00:14:43,300 --> 00:14:46,910
Это случается практически
в каждом пользовательском UI.

341
00:14:46,910 --> 00:14:49,870
И мы хотим подеиться ресурсами
через несколько Fragments

342
00:14:49,870 --> 00:14:51,250
или Activities.

343
00:14:51,250 --> 00:14:54,580
Местоположение устройства одинаково
от фрагмента

344
00:14:54,580 --> 00:14:55,240
к фрагменту.

345
00:14:55,240 --> 00:14:57,040
И если у вас два Fragment'a,
почему вы должны создавать

346
00:14:57,040 --> 00:15:01,610
два Listener'a, чтобы слушать
одно и то же местоположение?

347
00:15:01,610 --> 00:15:05,080
Следовательно, мы создали
новую штуку: LiveData.

348
00:15:05,080 --> 00:15:06,600
Давайте посмотрим что это.

349
00:15:06,600 --> 00:15:10,390
Итак, LiveData это держатель данных,
он просто содержит некоторые данные.

350
00:15:10,390 --> 00:15:13,690
Это похоже на слушателя, но
LiveData более хитрая вещь,

351
00:15:13,690 --> 00:15:15,760
которая знает о жизненном цикле.

352
00:15:15,760 --> 00:15:18,310
Он понимает жизненный цикл.

353
00:15:18,310 --> 00:15:20,820
Он понимает о жизненном
цикле потому,

354
00:15:20,820 --> 00:15:22,850
что автоматически
управляет подписками.

355
00:15:22,850 --> 00:15:25,220
Так что очень похоже
на предыдущий пример,

356
00:15:25,220 --> 00:15:29,290
и если вы наблюдаете LiveData,
вам нет необходимости отписываться.

357
00:15:29,290 --> 00:15:33,040
Нужные вещи будут происходить
в нужное время.

358
00:15:33,040 --> 00:15:37,660
Так что если бы LocationListener
был LiveData, и был singleton

359
00:15:37,660 --> 00:15:40,000
потому что метоположение это
singleton, мы могли бы

360
00:15:40,000 --> 00:15:41,800
написать что-то вроде этого -

361
00:15:41,800 --> 00:15:43,930
getInstance(), начать наблюдение.

362
00:15:43,930 --> 00:15:47,280
И когда вы наблюдаете, вы
говорите: "Это мой жизненный цикл".

363
00:15:47,280 --> 00:15:48,280
Это все, что вам нужно сделать.

364
00:15:48,280 --> 00:15:51,880
Раньше на Android, если вы
наблюдали что-то, что было singleton

365
00:15:51,880 --> 00:15:55,180
из Activity, каждый
снизит вам два балла

366
00:15:55,180 --> 00:15:56,650
при обзоре этого кода.

367
00:15:56,650 --> 00:15:57,805
Теперь вы можете делать это.

368
00:15:57,805 --> 00:16:01,600
Это безопасно,
это не грозит утечками.

369
00:16:01,600 --> 00:16:03,790
Итак, если вы захотите изменить
ваш LocationListener

370
00:16:03,790 --> 00:16:07,430
используйте это API, мы
избавились от ненужных вещей.

371
00:16:07,430 --> 00:16:09,590
Все, что нам нужно,
Это Context для подключения.

372
00:16:09,590 --> 00:16:15,540
Что мы говорим: это LiveData,
это LiveData местоположения.

373
00:16:15,540 --> 00:16:18,110
и мы даем эти два
новых метода.

374
00:16:18,110 --> 00:16:20,520
Один из двух называется
onActive(), что значит

375
00:16:20,520 --> 00:16:22,920
у вас есть активный наблюдатель.

376
00:16:22,920 --> 00:16:24,475
Другой называется
onInactive(),

377
00:16:24,475 --> 00:16:27,555
что означает, что у вас нет
ни одного активного наблюдателя.

378
00:16:27,555 --> 00:16:30,360
Теперь, на данный момент, вы,
возможно, спрашиваете себя:

379
00:16:30,360 --> 00:16:32,590
"Что такое активный наблюдатель?"

380
00:16:32,590 --> 00:16:34,290
Хорошо, мы дадим определение
активному наблюдателю.

381
00:16:34,290 --> 00:16:37,710
Это наблюдатель который находится
в состоянии START или RESUME, который

382
00:16:37,710 --> 00:16:40,440
как пользователь Activity,
в настоящее время смотрит.

383
00:16:40,440 --> 00:16:43,020
Итак, если у вас есть наблюдатель
на заднем фоне,

384
00:16:43,020 --> 00:16:45,300
Нет никаких оснований полагать
что она не активна.

385
00:16:45,300 --> 00:16:47,190
Нет причин
обновлять Activity

386
00:16:47,190 --> 00:16:49,950
потому что пользователь никогда
не увидит, что там происходит.

387
00:16:49,950 --> 00:16:53,390


388
00:16:53,390 --> 00:16:56,130
Т.к. внутри нашего метода connect(),
все, что мы должны сделать

389
00:16:56,130 --> 00:16:58,540
это всякий раз, когда
LocationManager отправляет нам

390
00:16:58,540 --> 00:17:02,120
новое местоположение, мы
вызываем setValue() с ним.

391
00:17:02,120 --> 00:17:05,589
Тогда LiveData знает какие
наблюдатели активны,

392
00:17:05,589 --> 00:17:08,410
и предоставляет данные
этим наблюдателям.

393
00:17:08,410 --> 00:17:11,930
Или, если один из наблюдателей
был в фоне

394
00:17:11,930 --> 00:17:14,290
и зате снова стал
видимым, то LiveData

395
00:17:14,290 --> 00:17:17,079
Позаботится о том, чтобы
отправить последние данные.

396
00:17:17,079 --> 00:17:19,608
этому наблюдателю.

397
00:17:19,608 --> 00:17:22,858
И тогда мы сможем сделать наш
LocationListener singleton объектом

398
00:17:22,858 --> 00:17:26,019
потому как мы не нуждаемся
в нескольких экземплярах.

399
00:17:26,020 --> 00:17:30,400
Итак, если мы взглянем на LiveData, то
это жизненный цикл знающий о наблюдателе.

400
00:17:30,400 --> 00:17:32,520
Это очень просто начать и
остановить эти действия.

401
00:17:32,520 --> 00:17:34,650
Не важно как много
у вас наблюдателей,

402
00:17:34,650 --> 00:17:39,740
или в каком они состоянии, вы
сливаете их в один жизненный цикл.

403
00:17:39,740 --> 00:17:42,000
И этого нет ни в
Activities, ни в Fragments

404
00:17:42,000 --> 00:17:44,620
внутри их, но это работает
с любыми из них.

405
00:17:44,620 --> 00:17:47,460
И LiveData тестировалась,
потому что

406
00:17:47,460 --> 00:17:49,080
Android открытая платформа.

407
00:17:49,080 --> 00:17:52,720
И если вы знакомы с печально
известной FragmentTransaction

408
00:17:52,720 --> 00:17:56,670
exception, мы гарантируем вам,
что наблюдатель никогда не будет,

409
00:17:56,670 --> 00:17:59,750
вызван в состоянии,
когда вы не сможете запустить

410
00:17:59,750 --> 00:18:01,260
вашу FragmentTransaction.

411
00:18:01,260 --> 00:18:03,780
Итак, это очень и очень
особенно разработанные средства

412
00:18:03,780 --> 00:18:08,100
для работы с вашими
Activities и Fragments.

413
00:18:08,100 --> 00:18:11,520
OK, давайте поговорим
о смене ориентации экрана.

414
00:18:11,520 --> 00:18:14,460
Ну, этот пример был легким
т.к. местоположение является глобальным,

415
00:18:14,460 --> 00:18:17,550
Но в большинстве случаев,
данные связаны с UI.

416
00:18:17,550 --> 00:18:22,770
Итак, если у нас есть Activity,
где показывается профиль пользователя,

417
00:18:22,770 --> 00:18:24,660
и мы добавили веб-сервис
который может вернуть

418
00:18:24,660 --> 00:18:28,260
данные как LiveData,
которые мы можем безопасно

419
00:18:28,260 --> 00:18:32,580
наблюдать, не опасаясь
утечки из Activity,

420
00:18:32,580 --> 00:18:33,470
это выглядит прекрасно.

421
00:18:33,470 --> 00:18:35,030
Мы никогда не упустим
эту Activity,

422
00:18:35,030 --> 00:18:36,390
это будет работать очень хорошо.

423
00:18:36,390 --> 00:18:40,340
Исключая... Что случится если
пользователь повернет устройство?

424
00:18:40,340 --> 00:18:42,850
Давайте взглянем на линию
жизненного цикла снова.

425
00:18:42,850 --> 00:18:44,790
Итак, Activity создано,
это запомнили, OK.

426
00:18:44,790 --> 00:18:46,752
Получаем пользователя.

427
00:18:46,752 --> 00:18:48,460
И пока мы получаем
[проверяем accaunt] пользователя,

428
00:18:48,460 --> 00:18:51,390
пользователь решает
поверну-ка я телефон.

429
00:18:51,390 --> 00:18:53,130
и тогда Activity
разрушится.

430
00:18:53,130 --> 00:18:55,740
К счастью, мы не получили
утечку, это здорово.

431
00:18:55,740 --> 00:18:57,810
Но когда наше новое
Activity запустилось,

432
00:18:57,810 --> 00:18:59,620
делаем новый вызов.

433
00:18:59,620 --> 00:19:02,160
Ну, ничего страшного, но не айс.

434
00:19:02,160 --> 00:19:03,640
Чего мы хотим?

435
00:19:03,640 --> 00:19:05,700
Мы хотим реально удерживать
эти данные, правильно?

436
00:19:05,700 --> 00:19:09,870
Мы уже отправляли это запрос,
зачем отправлять его опять?

437
00:19:09,870 --> 00:19:12,780
Мы хотим, чтобы наш график
выглядел так.

438
00:19:12,780 --> 00:19:14,640
Итак, если новая Activity
появляется, нам следует

439
00:19:14,640 --> 00:19:18,330
быть способными вернуть ту же
view model, которая и есть

440
00:19:18,330 --> 00:19:20,340
новый класс называемый ViewModel.

441
00:19:20,340 --> 00:19:22,290
Итак, мы представляем этот
новый класс

442
00:19:22,290 --> 00:19:23,760
очень спецефичный для
этой вещи, где

443
00:19:23,760 --> 00:19:27,210
вам следует поместить данные
внутри вашей Activity

444
00:19:27,210 --> 00:19:30,940
во ViewModel, и сделать вашу
Activity свободной от данных.

445
00:19:30,940 --> 00:19:33,000
Итак, если вы хотите
изменить эту Activity,

446
00:19:33,000 --> 00:19:36,910
вы создаете этот новый класс,
наследуемый от VewModel class.

447
00:19:36,910 --> 00:19:41,830
Независимо от того, какие данные
были внутри Activity, мы помещаем их

448
00:19:41,830 --> 00:19:45,630
во ViewModel-класс, и там, все,
что мы делаем, делаем внутри getUser(),

449
00:19:45,630 --> 00:19:48,790
если это первый запуск,
получаем данные из веб-службы.

450
00:19:48,790 --> 00:19:51,800
Иначе, возвращаем
текущее значение.

451
00:19:51,800 --> 00:19:53,220
Теперь, супер просто.

452
00:19:53,220 --> 00:19:55,800
И внутри нашей Activity мы
избавляемся от всего этого кода.

453
00:19:55,800 --> 00:19:58,590
Мы говорим получить
ViewModelProviders.of(this)

454
00:19:58,590 --> 00:20:01,620
В каждой Activity или Fragment'е
есть ViewModelProvider

455
00:20:01,620 --> 00:20:04,680
который вы можете получить, и
этот ViewModelProvider знает

456
00:20:04,680 --> 00:20:06,510
как предоставить вам ViewModel.

457
00:20:06,510 --> 00:20:08,880
Итак, когда вы вызываете
get(MyViewModel),

458
00:20:08,880 --> 00:20:10,530
в самый первый раз
вы делаете этот вызов,

459
00:20:10,530 --> 00:20:11,940
мы даем вам новое состояние.

460
00:20:11,940 --> 00:20:13,780
Когда вращение Activity
завершилось,

461
00:20:13,780 --> 00:20:16,760
начинается переподключение
к той же ViewModel.

462
00:20:16,760 --> 00:20:19,432
А затем и остального
этого кода также.

463
00:20:19,432 --> 00:20:22,318
[АПЛОДИСМЕНТЫ]

464
00:20:22,318 --> 00:20:28,580


465
00:20:28,580 --> 00:20:31,060
Итак, если вы посмотрите на
жизненный цикл, он выглядит так.

466
00:20:31,060 --> 00:20:32,040
Это то, чего мы хотели.

467
00:20:32,040 --> 00:20:35,800
Новая Activity запускается,
затем переподключается.

468
00:20:35,800 --> 00:20:38,140
И когда новая
Activity завершается,

469
00:20:38,140 --> 00:20:41,050
Например, когда нам нечего
делать с этой Activity,

470
00:20:41,050 --> 00:20:42,580
и тогда мы идем
и говорим ViewModel,

471
00:20:42,580 --> 00:20:44,350
что он больше не нужен.

472
00:20:44,350 --> 00:20:48,340
Это на самом деле единственный
метод во ViewModel классе.

473
00:20:48,340 --> 00:20:49,570
Так что это очень просто.

474
00:20:49,570 --> 00:20:51,640
Поэтому, если мы посмотрим на
жизненные циклы, они

475
00:20:51,640 --> 00:20:53,310
хранят данные для Activity.

476
00:20:53,310 --> 00:20:56,500
Они выживают при
изменениях конфигурации.

477
00:20:56,500 --> 00:20:58,930
Они никогда не должны,
каждый раз ссылаться на Views

478
00:20:58,930 --> 00:21:00,870
потому что они [НЕРАЗБОРЧИВО]
покидают эти Activities.

479
00:21:00,870 --> 00:21:03,430
Итак, вы не можете ссылаться
обратно на Activity.

480
00:21:03,430 --> 00:21:05,640
Вот почему вы используете
такие вещи, как LiveData,

481
00:21:05,640 --> 00:21:08,550
Rx Java, или наблюдатели
с хранением данных

482
00:21:08,550 --> 00:21:10,270
чтобы совершать эту коммуникацию.

483
00:21:10,270 --> 00:21:12,730
И это то, почему все наши
разговоры про Activity - это всегда

484
00:21:12,730 --> 00:21:15,070
разговоры о ViewModel.

485
00:21:15,070 --> 00:21:19,210
Теперь еще одна большая
тема о поддержке сохранности данных.

486
00:21:19,210 --> 00:21:22,000
Теперь мы знаем, написать хорошее,
отзывчивое приложение на Android

487
00:21:22,000 --> 00:21:24,860
означает и то, что необходимо
сохранять данные на диск.

488
00:21:24,860 --> 00:21:27,700
Если мы взглянем на Android, там
есть 3-4 основных API для этого.

489
00:21:27,700 --> 00:21:29,980
Один из которых это
ContentProvider, который

490
00:21:29,980 --> 00:21:32,320
переносит данные между процессами.

491
00:21:32,320 --> 00:21:35,530
В реальности это не имеет
общего с сохранением данных.

492
00:21:35,530 --> 00:21:37,510
Другой способ это
SharedPreferences,

493
00:21:37,510 --> 00:21:40,090
который сохраняет данные в XML.

494
00:21:40,090 --> 00:21:43,190
Вы можете сохранить только
немного данных с его помощью.

495
00:21:43,190 --> 00:21:44,800
Последний способ это
SQLite, которая

496
00:21:44,800 --> 00:21:48,160
была введена с версии
Android 1.

497
00:21:48,160 --> 00:21:49,720
Итак, вы знаете, вам
нужно использовать SQLite

498
00:21:49,720 --> 00:21:51,890
если вы хотите хранить много данных.

499
00:21:51,890 --> 00:21:55,330
Вы идете на
developer.android.com/ это

500
00:21:55,330 --> 00:21:57,960
самое первое сохранение
ваших данных.

501
00:21:57,960 --> 00:22:00,130
Это очень запутывает.

502
00:22:00,130 --> 00:22:01,642
Это очень грустно.

503
00:22:01,642 --> 00:22:03,370
[СМЕХ]

504
00:22:03,370 --> 00:22:06,190
Итак - OK, мы хотим
сделать это менее грустным.

505
00:22:06,190 --> 00:22:07,960
Мы хотим сделать это приятным.

506
00:22:07,960 --> 00:22:10,060
Итак, посмотрим на
пример, правильно?

507
00:22:10,060 --> 00:22:11,740
Так что - сверху,
он пытается сказать,

508
00:22:11,740 --> 00:22:15,670
"Я хочу выбрать эти три
столбца с таким-то условием,

509
00:22:15,670 --> 00:22:17,950
и я хочу отсортировать
результат так-то."

510
00:22:17,950 --> 00:22:20,670
Это на самом деле,
довольно простой SQL-запрос,

511
00:22:20,670 --> 00:22:22,210
но вам нужно написать
весь этот код.

512
00:22:22,210 --> 00:22:24,160
Плюс, этот код
даже не показывает где

513
00:22:24,160 --> 00:22:27,720
вы определяете все эти константы.

514
00:22:27,720 --> 00:22:29,430
Чего же мы хотим на самом деле?

515
00:22:29,430 --> 00:22:32,060
мы хотим избавиться от этого
кода без шаблонов.

516
00:22:32,060 --> 00:22:34,890
Когда вы пишете на Java,
если вы делаете опечатку в Java,

517
00:22:34,890 --> 00:22:36,630
он не компилирует код.

518
00:22:36,630 --> 00:22:39,010
Мы хотим похожую вещь для SQL.

519
00:22:39,010 --> 00:22:42,000
Мы все еще хотим использовать SQLite,
потому что на каждом девайсе Android

520
00:22:42,000 --> 00:22:43,740
есть эта проверенная технология.

521
00:22:43,740 --> 00:22:46,230
Мы знаем, это отлично работает.

522
00:22:46,230 --> 00:22:48,280
Но мы хотим проверять
компиляцию на лету.

523
00:22:48,280 --> 00:22:49,970
Поэтому мы не хотим
код по шаблонам,

524
00:22:49,970 --> 00:22:52,480
мы хотим проверять компиляцию
на лету, в реальном времени.

525
00:22:52,480 --> 00:22:56,220
Мы сказали "ОК - мы пришли с
Room, которая является объектом

526
00:22:56,220 --> 00:22:59,649
mapping library для SQLite". [т.е. ORM]

527
00:22:59,649 --> 00:23:05,800
[АПЛОДИСМЕНТЫ]

528
00:23:05,800 --> 00:23:08,210
Если мы посмотрим на
этот запрос, мы скажем,

529
00:23:08,210 --> 00:23:10,770
"OK, давайте поместим этот
запрос под аннотацию.

530
00:23:10,770 --> 00:23:12,610
Мы любим аннотации".

531
00:23:12,610 --> 00:23:14,560
И у нас есть объект
Feed, который

532
00:23:14,560 --> 00:23:16,360
мы хотим сохранить в базе данных.

533
00:23:16,360 --> 00:23:19,270
Я хочу поместить этот запрос
внутри интерфейса.

534
00:23:19,270 --> 00:23:21,280
Вы хотите создать FeedDao -

535
00:23:21,280 --> 00:23:24,040
Dao означает
Data Access Object.

536
00:23:24,040 --> 00:23:27,430
Обычно для баз данных, лучший
способ разместить там данные

537
00:23:27,430 --> 00:23:29,350
это сделать это через абстракцию.

538
00:23:29,350 --> 00:23:32,252
Тогда, нам всего лишь нужно
сказать Room "это DAO".

539
00:23:32,252 --> 00:23:34,360
Сказать Room: "это сущность".

540
00:23:34,360 --> 00:23:37,960
И наконец, у нас был класс
базы данных, который говорил:

541
00:23:37,960 --> 00:23:41,050
"Что у меня есть сущности -
поэтому есть несколько сущностей,

542
00:23:41,050 --> 00:23:45,240
и у меня есть данные для доступа
к объектам, которые вы видели.

543
00:23:45,240 --> 00:23:46,210
Это все, что вы пишите.

544
00:23:46,210 --> 00:23:48,760
Как только вы напишите это, вы
можете получить реализацию этого

545
00:23:48,760 --> 00:23:49,590
с помощью Room.

546
00:23:49,590 --> 00:23:52,750
Это очень похоже на то, когда
вы используете Retrofit или Dagger -

547
00:23:52,750 --> 00:23:57,080
вы определяете интерфейсы,
мы обеспечиваем реализацию.

548
00:23:57,080 --> 00:23:59,740
Теперь, как только мы узнали,
что это DAO, мы можем

549
00:23:59,740 --> 00:24:01,210
использовать методы быстрого доступа.

550
00:24:01,210 --> 00:24:05,350
Такие как, insert() это, или
deleteAll() это, or updateAll() -

551
00:24:05,350 --> 00:24:06,930
Куча методов бытрого доступа.

552
00:24:06,930 --> 00:24:08,710
Вы можете задавать
множесто параметров.

553
00:24:08,710 --> 00:24:11,115
Так много, пока сможете читать.
И это имеет смысл,

554
00:24:11,115 --> 00:24:13,930
Room поймет их.

555
00:24:13,930 --> 00:24:16,000
Но наиболее важная
часть Room - это то,

556
00:24:16,000 --> 00:24:18,680
что он понимает ваш SQL.

557
00:24:18,680 --> 00:24:20,320
Итак часть - все те
константы, о которых

558
00:24:20,320 --> 00:24:23,630
я упомянул, мы определили, чтобы
избежать ошибок во время компиляции,

559
00:24:23,630 --> 00:24:26,560
Room реально дает это
все бесплатно.

560
00:24:26,560 --> 00:24:28,380
Поэтому, когда Room видит
этот запрос, то говорит:

561
00:24:28,380 --> 00:24:31,060
"ОК, вы получаете эти
три столбца

562
00:24:31,060 --> 00:24:34,900
из этой таблицы, где название
похоже на это ключевое слово.

563
00:24:34,900 --> 00:24:36,705
Откуда это
ключевое слово?

564
00:24:36,705 --> 00:24:38,710
О, да оно приходит
из параметров функции.

565
00:24:38,710 --> 00:24:39,567
Имеет смысл.

566
00:24:39,567 --> 00:24:40,900
И что она хочет вернуть?

567
00:24:40,900 --> 00:24:42,970
Она хочет вернуть
список объектов Feed."

568
00:24:42,970 --> 00:24:45,330
И тогда Room идет и проверяет.

569
00:24:45,330 --> 00:24:47,980
"Подходят ли эти столбцы
к объекту, который

570
00:24:47,980 --> 00:24:49,690
пользователь хочет вернуть?"

571
00:24:49,690 --> 00:24:53,812
И, как только они равны, говорится:
"OK, я могу сгенерировать этот код."

572
00:24:53,812 --> 00:24:55,270
Вы можете даже, скажем,
выбрать звездочку [все столбцы].

573
00:24:55,270 --> 00:24:56,600
Вам не нужно их перечислять.

574
00:24:56,600 --> 00:25:00,190
Room реально, реально
понимает ваш запрос.

575
00:25:00,190 --> 00:25:03,130
Вы можете даже соединить 10
таблиц, и это все еще будет работать.

576
00:25:03,130 --> 00:25:05,020
Но что, если вы сделали опечатку?

577
00:25:05,020 --> 00:25:07,750
Вместо того, чтобы написать
"feed" вы пишите "feeds".

578
00:25:07,750 --> 00:25:10,750
Теперь, если это случится,
Room собирается дать вам

579
00:25:10,750 --> 00:25:12,940
ошибку времени компиляции.

580
00:25:12,940 --> 00:25:15,040
Так что выходит, что
ваш запрос проверяется

581
00:25:15,040 --> 00:25:17,080
по схеме, которую
вы определили.

582
00:25:17,080 --> 00:25:19,562
И вам сообщается, если
вы где-то ошиблись.

583
00:25:19,562 --> 00:25:22,508
[АПЛОДИСМЕНТЫ]

584
00:25:22,508 --> 00:25:27,797


585
00:25:27,797 --> 00:25:29,380
Но это не единственное,
что Room делает.

586
00:25:29,380 --> 00:25:30,860
Итак, если вы скажите -

587
00:25:30,860 --> 00:25:34,070
если ваш запрос верен, вы
хотите получить ID и title.

588
00:25:34,070 --> 00:25:35,870
Говорится: "Хорошо,
это запрос, но вы

589
00:25:35,870 --> 00:25:37,350
хотите вернуть это как строку."

590
00:25:37,350 --> 00:25:40,460
И тогда Room отвечает: "ОК, ты
возвращаешь две колонки,

591
00:25:40,460 --> 00:25:42,260
но у тебя есть только одна строка.

592
00:25:42,260 --> 00:25:43,320
Это не имеет смысла."

593
00:25:43,320 --> 00:25:46,800
И это обратно выдаст вам
ошибку во время компиляции.

594
00:25:46,800 --> 00:25:49,220
И это действительно хороший
способ исправить это в Room.

595
00:25:49,220 --> 00:25:51,095
Вы можете в принципе
создать любой Java класс.

596
00:25:51,095 --> 00:25:52,580
Это не нужно
аннотировать,

597
00:25:52,580 --> 00:25:55,170
Не надо говорить ничего
специально об этом Pojo,

598
00:25:55,170 --> 00:25:57,080
просто сказать Room вернуть его.

599
00:25:57,080 --> 00:25:59,780
Пока какой-либо запрос
возвращает то, что

600
00:25:59,780 --> 00:26:01,880
соответствует тому,
что вы хотите вернуть,

601
00:26:01,880 --> 00:26:05,250
Room напишет этот код
вместо вас.

602
00:26:05,250 --> 00:26:07,470
И теперь наблюдатели, которые
очень важны, не так ли?

603
00:26:07,470 --> 00:26:09,390
Если у вас есть запрос,
подобный этому, то вы

604
00:26:09,390 --> 00:26:11,460
показывая список Feed'ов,
вы очевидно

605
00:26:11,460 --> 00:26:14,295
захотите получить уведомление,
когда данные изменятся.

606
00:26:14,295 --> 00:26:17,842
И в Room, если вы хотите
сделать это, вы можете

607
00:26:17,842 --> 00:26:19,290
сказать и сделать. Скажите,

608
00:26:19,290 --> 00:26:22,980
чтобы она вернул LiveData,
и она сделает это для вас.

609
00:26:22,980 --> 00:26:26,400
Потому что она знает ваш запрос,
знает, что на него влияет.

610
00:26:26,400 --> 00:26:29,520
Таким образом это поможет вам
узнать, если запрос изменится.

611
00:26:29,520 --> 00:26:32,280
И это та часть, где все эти
архитектурные компоненты

612
00:26:32,280 --> 00:26:33,750
прекрасно работают вместе.

613
00:26:33,750 --> 00:26:36,640
Room уже знает
о LiveData.

614
00:26:36,640 --> 00:26:40,340
Итак ваша ViewModel, все, что вы
можете написать - из данных,

615
00:26:40,340 --> 00:26:42,600
вызовите этот запрос, и
это все он сделает.

616
00:26:42,600 --> 00:26:46,650
Всякий раз, когда данные меняются,
ваш UI обновляется также.

617
00:26:46,650 --> 00:26:49,470
И это только тогда происходит
когда ваш UI виден [visible]

618
00:26:49,470 --> 00:26:52,958
И последнее, но не менее важное,
Room также поддерживает RxJava 2.

619
00:26:52,958 --> 00:26:55,448
[ОВАЦИИ]

620
00:26:55,448 --> 00:27:01,930


621
00:27:01,930 --> 00:27:04,390
OK, если сказать о
Room в двух словах,

622
00:27:04,390 --> 00:27:06,730
Она пишет шаблонный
код для вас [вместо вас].

623
00:27:06,730 --> 00:27:08,050
И она полностью поддерживает SQLite.

624
00:27:08,050 --> 00:27:10,990
Вы можете все просто писать на
SQLite, будет работать и так.

625
00:27:10,990 --> 00:27:14,070
Она проверяет ваши запросы
во время компиляции.

626
00:27:14,070 --> 00:27:17,350
Это стимулирует лучшие практики,
которые помогают вам

627
00:27:17,350 --> 00:27:19,480
с тестами, миграцией и.

628
00:27:19,480 --> 00:27:23,020
также наблюдателями, и все
это прямо из коробки.

629
00:27:23,020 --> 00:27:28,000
OK, архитектура,
наша последняя тема на сегодня.

630
00:27:28,000 --> 00:27:30,000
Итак, с чего мы начали, верно?

631
00:27:30,000 --> 00:27:31,860
И теперь вы, возможно,
спросите себя:

632
00:27:31,860 --> 00:27:34,335
"Что изменилось в
2017 году, что вы вдруг

633
00:27:34,335 --> 00:27:36,930
заговорили про архитектуру?"

634
00:27:36,930 --> 00:27:38,740
Хорошо, реально
ничего не изменилось.

635
00:27:38,740 --> 00:27:40,560
Мы говорим об этой теме
много.

636
00:27:40,560 --> 00:27:44,460
Adam Powell и я вели много
разговоров на эту тему.

637
00:27:44,460 --> 00:27:49,050
Этот разговор начался с 2010,
который я наблюдаю как разработчик.

638
00:27:49,050 --> 00:27:51,630
И это та тема, которую мы
вполне четко обсуждали.

639
00:27:51,630 --> 00:27:54,720
Но чего не хватало, так это
четко определенной ссылки

640
00:27:54,720 --> 00:27:56,022
на архитектуру.

641
00:27:56,022 --> 00:27:57,480
И это то, что мы
запускаем в эти дни.

642
00:27:57,480 --> 00:27:59,370
Если вы пройдете сегодня на
developer.android.com,

643
00:27:59,370 --> 00:28:01,680
после нашей сессии,
есть секция

644
00:28:01,680 --> 00:28:05,246
о том, как быть архитектором
в Android приложении.

645
00:28:05,246 --> 00:28:08,697
[АПЛОДИСМЕНТЫ]

646
00:28:08,697 --> 00:28:13,640


647
00:28:13,640 --> 00:28:15,890
И, таким образом, это
гид по архитектуре.

648
00:28:15,890 --> 00:28:17,780
Это не книга догматических правил.

649
00:28:17,780 --> 00:28:20,600
Мы верим, что это очень хороший
путь, чтобы писать приложения,

650
00:28:20,600 --> 00:28:24,320
но вы не обязаны, следовать
за нами строчка за строчкой.

651
00:28:24,320 --> 00:28:27,400
Поэтому я кратко остановлюсь
на архитектуре,

652
00:28:27,400 --> 00:28:28,960
но если вы потеряетесь немного,
не волнуйтесь.

653
00:28:28,960 --> 00:28:31,950
У нас есть вся документации на
developer.аndroid.com

654
00:28:31,950 --> 00:28:34,264
с простыми примерами.

655
00:28:34,264 --> 00:28:35,680
Итак, мы считаем, что
приложение состоит

656
00:28:35,680 --> 00:28:37,300
из четырех главных частей -

657
00:28:37,300 --> 00:28:41,680
это UI-контроллеры,
ViewModels, хранилище данных,

658
00:28:41,680 --> 00:28:43,030
и источники данных.

659
00:28:43,030 --> 00:28:45,640
Давайте разберем это
в деталях.

660
00:28:45,640 --> 00:28:47,980
UI-контроллеры это
ваши Activities,

661
00:28:47,980 --> 00:28:51,100
Fragments, custom Views.

662
00:28:51,100 --> 00:28:52,750
У них действительно простые задачи.

663
00:28:52,750 --> 00:28:55,270
Они наблюдают за полями
у ViewModel

664
00:28:55,270 --> 00:28:56,720
и обновляют себя.

665
00:28:56,720 --> 00:28:58,540
И они хотят больше
ответственности.

666
00:28:58,540 --> 00:29:01,540
Всякий раз, когда пользователь
совершает действие в UI,

667
00:29:01,540 --> 00:29:04,450
они понимают это действие,
и сообщают о нем во ViewModel

668
00:29:04,450 --> 00:29:07,540
так, что становится понятно,
что пользователь хотел сделать.

669
00:29:07,540 --> 00:29:10,390
Если мы посмотрим на ViewModel,
то это та сущность, которая

670
00:29:10,390 --> 00:29:13,450
готовит данные
для UI,

671
00:29:13,450 --> 00:29:14,480
и держит их.

672
00:29:14,480 --> 00:29:16,740
Это то, где данные
для UI-интерфейса.

673
00:29:16,740 --> 00:29:20,050
ViewModel знает как
получить эти данные.

674
00:29:20,050 --> 00:29:21,949
Обычно есть LiveData.

675
00:29:21,949 --> 00:29:23,740
Если вы используете RxJava,
это наблюдение за данными,

676
00:29:23,740 --> 00:29:26,940
или сбор информации от наблюдений.

677
00:29:26,940 --> 00:29:28,830
Это помогает "пережить"
изменения конфигурации.

678
00:29:28,830 --> 00:29:32,200
И это то, почему мы помещаем
данные во ViewModels.

679
00:29:32,200 --> 00:29:33,680
И это также шлюз.

680
00:29:33,680 --> 00:29:37,040
И это тоже понятно т.к.
ваш UI-контроллер, когда

681
00:29:37,040 --> 00:29:39,230
говорит с ViewModel,
связывается с остальными

682
00:29:39,230 --> 00:29:42,690
частями приложения.

683
00:29:42,690 --> 00:29:44,360
И что же тогда репозиторий?

684
00:29:44,360 --> 00:29:47,100
ViewModel выполняет функцию
хранилища данных

685
00:29:47,100 --> 00:29:48,920
для UI-контроллера, правильно?

686
00:29:48,920 --> 00:29:51,060
Репозиторий хранит их,
в предсталении хранилища данных

687
00:29:51,060 --> 00:29:53,520
для всего вашего приложения.

688
00:29:53,520 --> 00:29:56,070
Таким образом, это полная
модель данных для приложения,

689
00:29:56,070 --> 00:29:58,560
и он обеспечивает обмен [предоставление]
данными через простые API

690
00:29:58,560 --> 00:30:00,210
для остальной части приложения.

691
00:30:00,210 --> 00:30:03,420
У вас может быть пользовательский
репозиторий, где вы даете user-ID,

692
00:30:03,420 --> 00:30:06,000
И получаете
LiveData о пользователе

693
00:30:06,000 --> 00:30:07,650
Откуда у него данные?

694
00:30:07,650 --> 00:30:10,260
Вы не должны заботиться,
это работа репозитория.

695
00:30:10,260 --> 00:30:11,280
Но как он это делает?

696
00:30:11,280 --> 00:30:12,420
Он беседует с -

697
00:30:12,420 --> 00:30:15,920
выборкой, синхронизацией,
глядя на базу данных,

698
00:30:15,920 --> 00:30:17,990
или общаясь через ваш
Retrofit.

699
00:30:17,990 --> 00:30:20,770
Это работа репозитория.

700
00:30:20,770 --> 00:30:23,100
И последнее но не менее важное,
у нас есть источники данных,

701
00:30:23,100 --> 00:30:25,020
наподобие ваших REST API клиентов.

702
00:30:25,020 --> 00:30:28,470
Вы можете использовать Retrofit,
или у вас есть SQLite база.

703
00:30:28,470 --> 00:30:30,500
Вы можете использовать Room,
или вы можете использовать

704
00:30:30,500 --> 00:30:32,460
GRAM, это не слишком важно.

705
00:30:32,460 --> 00:30:34,920
И вы можете говорить
другим провайдерам контента

706
00:30:34,920 --> 00:30:36,390
из других процессов.

707
00:30:36,390 --> 00:30:39,090
Эти вещи мы называем
источниками данных.

708
00:30:39,090 --> 00:30:41,940
И мы думаем, что
все эти слои

709
00:30:41,940 --> 00:30:43,830
могут обнаруживать друг
друга чтобы создавать

710
00:30:43,830 --> 00:30:45,630
проверки зависимостей
в системе, которые мы будем

711
00:30:45,630 --> 00:30:47,370
использовать с помощью Dagger.

712
00:30:47,370 --> 00:30:49,800
Но мы также озознаем, что
понимание ситуации зависимости

713
00:30:49,800 --> 00:30:51,810
не очень легко.

714
00:30:51,810 --> 00:30:55,560
Это более сложная тема, и
иногда может быть излишней.

715
00:30:55,560 --> 00:30:57,750
И вы могли бы использовать
Service Locator, если

716
00:30:57,750 --> 00:31:01,560
вы чувствуете себя более
комфортно с ним.

717
00:31:01,560 --> 00:31:04,050
Итак, давайте вернемся к конкретному -

718
00:31:04,050 --> 00:31:06,700
пройдем через конкретный пример.

719
00:31:06,700 --> 00:31:10,110
Допустим, у нас есть UI, который
показывает профиль пользователя,

720
00:31:10,110 --> 00:31:12,380
и у нас есть источник
данных который - мы сохраняем

721
00:31:12,380 --> 00:31:16,080
данные в базе данных, также
можем получить их через сеть.

722
00:31:16,080 --> 00:31:18,210
Как мы получаем
эти две вещи?

723
00:31:18,210 --> 00:31:21,240
Хорошо, мы говорим, что сначала
нужен репозиторий пользователя.

724
00:31:21,240 --> 00:31:23,880
Пользовательский репозиторий знает,
что он должен проверять базу данных.

725
00:31:23,880 --> 00:31:25,680
Если там нет,
то сделать веб-запрос.

726
00:31:25,680 --> 00:31:28,500
Или между тем, также попытаться
запустить базу данных.

727
00:31:28,500 --> 00:31:30,750
Не имеет значения,
как делать это,

728
00:31:30,750 --> 00:31:32,820
но он [репозиторий] знает,
как создать LiveData

729
00:31:32,820 --> 00:31:36,780
пользователя или наблюдателя,
все равно кого.

730
00:31:36,780 --> 00:31:38,430
И тогда нам нужна
ViewModel, правильно,

731
00:31:38,430 --> 00:31:41,670
потому что данные для
UI живут в ViewModel.

732
00:31:41,670 --> 00:31:44,220
Итак мы создаем
ProfileViewModel,

733
00:31:44,220 --> 00:31:48,030
который "говорит" с репозиторием,
чтобы получить эту информацию.

734
00:31:48,030 --> 00:31:50,850
А затем реальный фрагмент
получает данные

735
00:31:50,850 --> 00:31:54,450
из ViewModel, так что,
если фрагмент возвращается,

736
00:31:54,450 --> 00:31:57,270
то LiveData будет в
ProfileViewModel.

737
00:31:57,270 --> 00:32:00,070
Но если фрагмент
исчезает полностью,

738
00:32:00,070 --> 00:32:01,680
мы избавляемся
от ViewModel,

739
00:32:01,680 --> 00:32:05,240
и данных, которые могут быть
собраны сборщиком мусора.

740
00:32:05,240 --> 00:32:07,100
Теперь, вся эта абстракция,
которую мы создали,

741
00:32:07,100 --> 00:32:10,640
если вы заметели, каждый отдельный
компонент говорит только о том, что

742
00:32:10,640 --> 00:32:14,520
находится прямо под ним, что помогает
масштабировать ваше приложение.

743
00:32:14,520 --> 00:32:16,340
И это также имеет
огромную побочную выгоду,

744
00:32:16,340 --> 00:32:18,260
которая называется тестированием.

745
00:32:18,260 --> 00:32:19,230
Вы же тестируете, правильно?

746
00:32:19,230 --> 00:32:24,500


747
00:32:24,500 --> 00:32:26,210
Итак, скажем, вы хотите
протестировать ваш UI.

748
00:32:26,210 --> 00:32:27,880
Сейчас люди говорят UI-
тестирование сложное.

749
00:32:27,880 --> 00:32:30,990
UI-тестирование -
да, это сложно.

750
00:32:30,990 --> 00:32:33,320
Но часто это сложно потому,
что вы пишете много кода

751
00:32:33,320 --> 00:32:35,290
внутри Activity.

752
00:32:35,290 --> 00:32:38,630
Теперь мы говорим, пиши
больше во ViewModel,

753
00:32:38,630 --> 00:32:41,510
и вы знаете, что UI только
говорит к ViewModel,

754
00:32:41,510 --> 00:32:43,520
так что вы можете избавиться от
двух остальных [частей архитектуры].

755
00:32:43,520 --> 00:32:47,170
Вам только нужно создать фальшивку
ViewModel для тестирование вашего UI.

756
00:32:47,170 --> 00:32:50,900
Тестирование вашего UI становится супер,
супер easy with Espresso.

757
00:32:50,900 --> 00:32:52,880
И у нас есть пример
приложения на GitHub

758
00:32:52,880 --> 00:32:56,346
где вы можете проверить
с [НЕРАЗБОРЧИВО].

759
00:32:56,346 --> 00:32:58,220
И то же самое, что
и для ViewModels.

760
00:32:58,220 --> 00:32:59,660
Если вы хотите протестировать
ViewModel,

761
00:32:59,660 --> 00:33:02,330
вы знаете, что это только
переговоры к репозиторию.

762
00:33:02,330 --> 00:33:05,860
вы заменяете его mock-
репозиторием, и все работает.

763
00:33:05,860 --> 00:33:08,570
И вы даже можете тестировать
ваши ViewModels

764
00:33:08,570 --> 00:33:11,150
на вашей главной машине, на JVM.

765
00:33:11,150 --> 00:33:12,780
И последнее, но не менее
важное, вы можете тестировать

766
00:33:12,780 --> 00:33:14,030
репозиторий таким же способом.

767
00:33:14,030 --> 00:33:16,040
Вам нужен mock-источник данных.

768
00:33:16,040 --> 00:33:21,000
Вы можете легко протестировать
свой репозиторий как JUnit тест.

769
00:33:21,000 --> 00:33:23,060
Я пониманию, что дал вам
много информации.

770
00:33:23,060 --> 00:33:26,420
У нас будет две сессии завтра,
и есть документация.

771
00:33:26,420 --> 00:33:29,630
Но теперь я хочу пригласить
нашего product-manager LUKAS

772
00:33:29,630 --> 00:33:32,646
рассказать, что будет дальше.

773
00:33:32,646 --> 00:33:35,574
[АПЛОДИСМЕНТЫ]

774
00:33:35,574 --> 00:33:41,425


775
00:33:41,425 --> 00:33:42,800
LUKAS BERGSTROM:
Как Yigit сказал,

776
00:33:42,800 --> 00:33:44,870
мы только много прошлись по поверхности.

777
00:33:44,870 --> 00:33:46,820
Но реально, мы скрыли
много деталей

778
00:33:46,820 --> 00:33:48,080
пока мы рассказывали это.

779
00:33:48,080 --> 00:33:50,420
Но, к счастью, вам не нужно
запоминать все,

780
00:33:50,420 --> 00:33:51,950
что вы теперь услышали.

781
00:33:51,950 --> 00:33:56,180
У нас много материала
для вас на

782
00:33:56,180 --> 00:33:58,910
developer.android.com/arch.

783
00:33:58,910 --> 00:34:03,305
И эта ссылка должна работать
через 21 минуту.

784
00:34:03,305 --> 00:34:06,260


785
00:34:06,260 --> 00:34:07,790
Мы хотели дать вам,
ребята, шанс сделать заметку

786
00:34:07,790 --> 00:34:10,219
в блоге или твитнуть об этом
раньше кого-нибудь еще.

787
00:34:10,219 --> 00:34:13,190
Вот почему мы придержали это.

788
00:34:13,190 --> 00:34:15,560
Итак, да, мы сделали
хорошую документацию

789
00:34:15,560 --> 00:34:18,469
и она обозначает приоритеты
для начала этого проекта, поскольку

790
00:34:18,469 --> 00:34:22,310
предоставление хорошего руководства
одна из гланым наших задач.

791
00:34:22,310 --> 00:34:24,800
Итак, вы собираетесь найти
углубленную документацию

792
00:34:24,800 --> 00:34:27,337
написанную с точки
зрения разработчика.

793
00:34:27,337 --> 00:34:29,420
Вы действительно найдете
содержательные примеры приложений

794
00:34:29,420 --> 00:34:31,280
и они покажут как создавать реальное.

795
00:34:31,280 --> 00:34:34,650
И как пример того, как
много работы пошло на это,

796
00:34:34,650 --> 00:34:36,139
у нас есть GitHub пример
приложения браузера, который

797
00:34:36,139 --> 00:34:39,440
вероятно имеет лучшее покрытие
для тестирования, чем большинство

798
00:34:39,440 --> 00:34:42,170
приложений, написанных этим парнем.

799
00:34:42,170 --> 00:34:44,820


800
00:34:44,820 --> 00:34:47,420
И, конечно, у нас есть гид
по архитектуре приложений,

801
00:34:47,420 --> 00:34:50,929
который внутри мы назвали
гид на время.

802
00:34:50,929 --> 00:34:53,210
И считаем, что
метка все еще применяется.

803
00:34:53,210 --> 00:34:55,639
Но даже, если вы не планируете,
использовать ваши рекомендации

804
00:34:55,639 --> 00:34:58,580
по архитектуре, мы считаем
вам следует посмотреть этот гид.

805
00:34:58,580 --> 00:35:04,010
Там есть принципы, которые мы думаем
применимы ко всем приложениям.

806
00:35:04,010 --> 00:35:07,760
И вы, вероятно, спросите себя
сделал я не -

807
00:35:07,760 --> 00:35:09,830
какое влияние это должно
оказывать на меня?

808
00:35:09,830 --> 00:35:13,160
Должен ли я поменять способ,
которым я все делаю?

809
00:35:13,160 --> 00:35:15,315
Вы знаете, если вы находитесь
в запуске нового проекта,

810
00:35:15,315 --> 00:35:16,940
или у вас есть существующее
приложение, но вы

811
00:35:16,940 --> 00:35:19,190
хотите улучшить его
архитектуру,

812
00:35:19,190 --> 00:35:22,100
тогда мы рекомендуем
взглянуть на этот материал.

813
00:35:22,100 --> 00:35:24,050
Это по-прежнему превью.

814
00:35:24,050 --> 00:35:26,790
Мы не будем бить версию
1.0 несколько месяцев,

815
00:35:26,790 --> 00:35:30,050
Но мы думаем, что это
готовое для вас, ребята,

816
00:35:30,050 --> 00:35:32,460
руководство, чтобы проверить и
использовать в своих проверках.

817
00:35:32,460 --> 00:35:34,250
Но, если вы счастливы
с тем, что у вас есть,

818
00:35:34,250 --> 00:35:37,360
вам не нужно переписывать
ваше приложение.

819
00:35:37,360 --> 00:35:39,530
Поэтому быть вместе в одном
духе, это не значит,

820
00:35:39,530 --> 00:35:41,890
что мы диктуем всем,
как поступать. Если

821
00:35:41,890 --> 00:35:44,590
вы довольны своей архитектурой,
то вам следует ее сохранить.

822
00:35:44,590 --> 00:35:46,510
Если вы довольны
вашей существующей ORM,

823
00:35:46,510 --> 00:35:48,820
вам не надо использовать Room.

824
00:35:48,820 --> 00:35:51,910
Архитектурные компоненты нужны
для удобной совместной работы,

825
00:35:51,910 --> 00:35:55,780
Но они действительно работают
отлично и сами по себе, отдельно.

826
00:35:55,780 --> 00:35:58,300
И смешивание и сопоставление
применяется не только

827
00:35:58,300 --> 00:36:04,730
к архитектурным компонентам,
но и к сторонним библиотекам.

828
00:36:04,730 --> 00:36:11,760
Итак - я жду, чтобы
этот слайд появился..

829
00:36:11,760 --> 00:36:14,389
Итак, вы можете
использовать, что у вас есть,

830
00:36:14,389 --> 00:36:16,680
и начинать интегрировать
архитектурные компоненты, где

831
00:36:16,680 --> 00:36:18,310
это имеет смысл.

832
00:36:18,310 --> 00:36:21,000
Итак, например, если вы
счастливы с RxJava,

833
00:36:21,000 --> 00:36:24,510
но вам реально нравятся
Lifecycle-зависимые компоненты

834
00:36:24,510 --> 00:36:27,360
которые Yigit только что показывал,
у вас есть эти самодовлеющие

835
00:36:27,360 --> 00:36:31,590
компоненты, вы можете использовать
LiveData совместно с RxJava.

836
00:36:31,590 --> 00:36:34,800
Итак, вы можете получить все
преимущества от RxJava действий,

837
00:36:34,800 --> 00:36:36,420
и теперь это будет Lifecycle-безопасно.

838
00:36:36,420 --> 00:36:39,510
Так что, наподобие лучшего
из обоих миров.

839
00:36:39,510 --> 00:36:41,760
И у нас есть дополнительная
инфа про интеграцию.

840
00:36:41,760 --> 00:36:45,890
Мы определенно смотрим на
много вещей внутри

841
00:36:45,890 --> 00:36:48,480
и это было бы неплохо,
если бы они были самодостаточны

842
00:36:48,480 --> 00:36:50,500
и Lifecycle-зависимы.

843
00:36:50,500 --> 00:36:53,460
И если вы
разработчик библиотеки,

844
00:36:53,460 --> 00:36:55,920
мы настоятельно рекомендуем
проверять жизненные циклы

845
00:36:55,920 --> 00:36:57,690
и LifecycleObserver
потому что мы думаем

846
00:36:57,690 --> 00:37:00,480
это реально яркое будущее
и есть много потенциала

847
00:37:00,480 --> 00:37:03,420
в создании библиотечных компонентов,
которые зависимы от жизненного

848
00:37:03,420 --> 00:37:07,870
цикла по умолчанию.
Но перед тем как сделать

849
00:37:07,870 --> 00:37:11,110
это, у нас есть еще много
для вас на I/O в этом году.

850
00:37:11,110 --> 00:37:15,310
У нас есть еще две беседы,
одна про жизненные циклы

851
00:37:15,310 --> 00:37:18,280
это даже более глубоко, чем
что мы покажем завтра

852
00:37:18,280 --> 00:37:20,020
утром.

853
00:37:20,020 --> 00:37:24,040
У нас есть еще Room
и поддержка сохранности данных

854
00:37:24,040 --> 00:37:25,480
немного раньше
чем о Room

855
00:37:25,480 --> 00:37:27,790
начнется в 12:30 завтра.

856
00:37:27,790 --> 00:37:31,950
И у нас будут люди, которые
хороше кумекают в архитектурных

857
00:37:31,950 --> 00:37:36,740
компонентах на песочнице
для всех на I/O.

858
00:37:36,740 --> 00:37:41,600
И у нас есть codelabs,
которыми мы очень довольны.

859
00:37:41,600 --> 00:37:43,890
И еще все впереди.

860
00:37:43,890 --> 00:37:46,100
Поэтому мы думаем, что мы
только слегка затронули области,

861
00:37:46,100 --> 00:37:48,260
с помощью которых мы можем
улучшить использование Android

862
00:37:48,260 --> 00:37:51,320
фреймворка, и мы также рассматриваем
применение этого подхода

863
00:37:51,320 --> 00:37:53,310
в других областях.

864
00:37:53,310 --> 00:37:54,980
Итак, некоторые вещи
уже работают.

865
00:37:54,980 --> 00:37:58,310
И мы также заинтересованы
слышать от вас, о том,

866
00:37:58,310 --> 00:37:59,720
чтобы вы хотели еще видеть.

867
00:37:59,720 --> 00:38:04,010
Так что приходите, говорите с нами,
что вам нравится, чего вам нехватает.

868
00:38:04,010 --> 00:38:06,800
И следите за обновлениями,
которые мы реально ждем от будущего

869
00:38:06,800 --> 00:38:08,570
Android разработки.

870
00:38:08,570 --> 00:38:09,310
Спасибо.

871
00:38:09,310 --> 00:38:11,460
[АПЛОДИСМЕНТЫ]

872
00:38:11,460 --> 00:00:00,000


20 08 2017

Теги заметки: