Видео. Architecture Components. Solving the Lifecycle Problem. Перевод субтитров.

Перевод английских субтитров на русские из видео Architecture Components: Solving the Lifecycle Problem. Начало 09.09.2017, конец - .09.2017. All rights reserved.

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

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

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

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

  • Handling Application & UI lifecycle on Android has always been a challenge for applications: subclassing, overriding, and entirely too much code in your Activity class leads to fragile, complicated application logic. Wouldn’t it be nice if this was easier? This session will cover a new approach to lifecycles and explore functionality that makes the problem dramatically easier. Be sure to also check out the other two “Architecture Components” sessions for more information on architecting better Android applications.

Перевод:

  • Управление жизненным циклом приложений и пользовательского интерфейса на Android всегда было проблемой для приложений: подклассы, переопределение и слишком много кода в классе Activity приводят к хрупкой, сложной логике приложений. Было бы неплохо, если бы это было проще? В этой сессии попробуем охватить новый подход к жизненным циклам и изучить функциональность, которая значительно упростит проблему. Обязательно ознакомьтесь с двумя другими разделами «Компоненты архитектуры» для получения дополнительной информации об архитектуре лучших приложений для Android.

Ссылки к видео:

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

2
00:00:06,201 --> 00:00:09,380
SERGEI VASILINETC:
Good morning, everyone.

3
00:00:09,380 --> 00:00:10,130
My name is Sergei.

4
00:00:10,130 --> 00:00:12,620
This is Adam and
Yigit with me today,

5
00:00:12,620 --> 00:00:15,780
and we will speak about
LifeCycle problems.

6
00:00:15,780 --> 00:00:21,240
So probably many of you attended
yesterday at Yigit's talk

7
00:00:21,240 --> 00:00:24,670
where he introduced new
architecture components.

8
00:00:24,670 --> 00:00:27,550
He introduced LiveData,
ViewModel, new persistence

9
00:00:27,550 --> 00:00:28,540
slide named Room.

10
00:00:28,540 --> 00:00:31,900
And today we will focus
on the LifeCycle part

11
00:00:31,900 --> 00:00:34,990
of these architectural
components.

12
00:00:34,990 --> 00:00:37,715
So we will speak again about
LiveData And ViewModel.

13
00:00:37,715 --> 00:00:41,140
We will speak about LifeCycle
honors and LifeCycle that

14
00:00:41,140 --> 00:00:45,210
are basics for these libraries.

15
00:00:45,210 --> 00:00:49,150
But we will have more details.

16
00:00:49,150 --> 00:00:51,890
We will have some reasoning
behind our decisions.

17
00:00:51,890 --> 00:00:56,360
So if you attended yesterday,
it will be still interesting.

18
00:00:56,360 --> 00:00:57,900
If you didn't
attend yesterday, we

19
00:00:57,900 --> 00:00:59,600
will reintroduce
all of these things

20
00:00:59,600 --> 00:01:03,370
so you will
understand everything.

21
00:01:03,370 --> 00:01:07,480
So let's see what we have today.

22
00:01:07,480 --> 00:01:11,280
Today we have an activity
in the fragments.

23
00:01:11,280 --> 00:01:14,300
I'll start with is that not
for length length but dozens

24
00:01:14,300 --> 00:01:17,330
and dozens line of lines.

25
00:01:17,330 --> 00:01:22,190
And this line's the results
from a very natural process.

26
00:01:22,190 --> 00:01:24,690
Google pay services
asked to register them

27
00:01:24,690 --> 00:01:25,670
in onStart methods.

28
00:01:25,670 --> 00:01:29,620
It's Your own components need
to know about this LifeCycle

29
00:01:29,620 --> 00:01:34,640
event, so you need to forward
them in some kind of API.

30
00:01:34,640 --> 00:01:38,100
And correspondingly,
on onStop method,

31
00:01:38,100 --> 00:01:42,530
you have to call all
pairings stop methods,

32
00:01:42,530 --> 00:01:44,900
and it's very easy
to forget one.

33
00:01:44,900 --> 00:01:46,880
And will result in [INAUDIBLE].

34
00:01:46,880 --> 00:01:51,950
It will drain the
user's battery,

35
00:01:51,950 --> 00:01:54,920
and they will enjoy
your app a bit less.

36
00:01:54,920 --> 00:01:58,190
Which is probably healthier for
them, but we think that's bad.

37
00:01:58,190 --> 00:02:02,180
And they think the
answer in this situation

38
00:02:02,180 --> 00:02:04,130
is to introduce LifeCycle
aware components.

39
00:02:04,130 --> 00:02:06,770
So components which
handle LifeCycle.

40
00:02:06,770 --> 00:02:08,538
And the first step
in this direction

41
00:02:08,538 --> 00:02:11,750
is to introduce LifeCycle
as a first class citizen.

42
00:02:11,750 --> 00:02:13,550
So it's a very
simple object which

43
00:02:13,550 --> 00:02:17,370
answers the question, what is
the current state right now?

44
00:02:17,370 --> 00:02:19,130
And notifies you
about new events.

45
00:02:19,130 --> 00:02:22,340
And then no feature is important
but sounds ridiculous right

46
00:02:22,340 --> 00:02:26,060
now, events and states
are different things.

47
00:02:26,060 --> 00:02:28,540
So let's see what I mean.

48
00:02:28,540 --> 00:02:31,610
Your case is instantiated
in initialized state.

49
00:02:31,610 --> 00:02:37,965
And all creation phases
pass very routinely.

50
00:02:37,965 --> 00:02:39,680
OnCreate, create the state.

51
00:02:39,680 --> 00:02:42,460
OnStart, start the state,
same thing for resume.

52
00:02:42,460 --> 00:02:45,070
But the road down is a
bit more interesting.

53
00:02:45,070 --> 00:02:48,920
So onPause event, leads
you from a resume state

54
00:02:48,920 --> 00:02:50,480
back to a starting state.

55
00:02:50,480 --> 00:02:53,490
Not some new pause state,
or something like that.

56
00:02:53,490 --> 00:02:57,870
And the reason for this is
from a system perspective,

57
00:02:57,870 --> 00:03:01,880
the states after onPause event
and onStart event are the same

58
00:03:01,880 --> 00:03:05,790
because the sets of the actions
that you are allowed to do

59
00:03:05,790 --> 00:03:07,010
is the same.

60
00:03:07,010 --> 00:03:11,960
And the same is true for
onStop and Creative state.

61
00:03:11,960 --> 00:03:14,350
And last event is onDestroy.

62
00:03:14,350 --> 00:03:18,390
It's pretty straightforward.

63
00:03:18,390 --> 00:03:20,150
It brings it to destroy state.

64
00:03:20,150 --> 00:03:21,730
Your activity is destroyed.

65
00:03:21,730 --> 00:03:25,720
It's going to be thrown
away and garbage collected.

66
00:03:25,720 --> 00:03:28,020
So let's make our
component LifeCycle aware.

67
00:03:28,020 --> 00:03:29,390
That's super straightforward.

68
00:03:29,390 --> 00:03:32,780
We take it with LifeCycle
observer interface,

69
00:03:32,780 --> 00:03:34,350
accepted interface.

70
00:03:34,350 --> 00:03:40,320
To get the actual events, we add
annotation and pass the events

71
00:03:40,320 --> 00:03:43,200
that we are interested in,
you can pass multiple events

72
00:03:43,200 --> 00:03:43,950
if you want to.

73
00:03:43,950 --> 00:03:48,180
The last step is to add
ourselves as an observer.

74
00:03:48,180 --> 00:03:53,910
And we may have a
potential problem here.

75
00:03:53,910 --> 00:03:57,810
What if the activity is
already started at this point?

76
00:03:57,810 --> 00:04:02,730
Does this mean that we are
going to receive onStop event,

77
00:04:02,730 --> 00:04:05,970
and and we didn't
receive onStart.

78
00:04:05,970 --> 00:04:09,540
And our component probably
is not ready for this.

79
00:04:09,540 --> 00:04:12,570
But it took care
of it, and we bring

80
00:04:12,570 --> 00:04:14,412
the observer to correct state.

81
00:04:14,412 --> 00:04:15,370
So what does this mean?

82
00:04:15,370 --> 00:04:17,670
Let's take this example,
which I just discussed.

83
00:04:17,670 --> 00:04:20,610
From activity perspective
onStart and onCreate

84
00:04:20,610 --> 00:04:26,250
create already happened, and
after that we add an observer.

85
00:04:26,250 --> 00:04:31,740
But observer will still receive
onCreate and onStart events

86
00:04:31,740 --> 00:04:34,950
immediately when
they were registered.

87
00:04:34,950 --> 00:04:38,130
So let's take one step further.

88
00:04:38,130 --> 00:04:39,870
OnResume, same situation.

89
00:04:39,870 --> 00:04:41,400
Resume state will
bring to resume

90
00:04:41,400 --> 00:04:45,550
state we got an onResume
event in addition to onCreate

91
00:04:45,550 --> 00:04:46,610
and onStart.

92
00:04:46,610 --> 00:04:48,660
A bit more
interesting situation,

93
00:04:48,660 --> 00:04:54,590
onPause In this situation, we
are in a start state as well as

94
00:04:54,590 --> 00:04:55,830
we learned.

95
00:04:55,830 --> 00:04:59,060
So we bring the oberserver
to the correct state

96
00:04:59,060 --> 00:05:00,030
which is start.

97
00:05:00,030 --> 00:05:04,040
So it's a similar situation
as we had one minute ago.

98
00:05:04,040 --> 00:05:06,930
Observer will receive
onCreate and onStart events,

99
00:05:06,930 --> 00:05:09,090
and that's it.

100
00:05:09,090 --> 00:05:13,460
So we don't have a
problem in this code.

101
00:05:13,460 --> 00:05:17,240
So how to get this
magical lifecycle object?

102
00:05:17,240 --> 00:05:20,940
We have this interface
which is super simple,

103
00:05:20,940 --> 00:05:25,060
but this probably doesn't
help much right now.

104
00:05:25,060 --> 00:05:26,580
And the actual
question is who are

105
00:05:26,580 --> 00:05:29,600
LifeCycle owners out of box.

106
00:05:29,600 --> 00:05:34,310
And the answer in this question
is support library fragments

107
00:05:34,310 --> 00:05:35,630
and support activities.

108
00:05:35,630 --> 00:05:40,140
But unfortunately, this is
true only in the bright future.

109
00:05:40,140 --> 00:05:44,300
And right now we have
LifeCycle activity

110
00:05:44,300 --> 00:05:46,040
and LifeCycle fragment.

111
00:05:46,040 --> 00:05:49,520
But at the point
of 1.0 release, we

112
00:05:49,520 --> 00:05:53,720
will merge our library to
support libraries so you

113
00:05:53,720 --> 00:05:56,070
don't have to use them later.

114
00:05:56,070 --> 00:05:59,400
And now Adam will speak
about some key differences

115
00:05:59,400 --> 00:06:02,242
between fragment and
LifeCyle observers

116
00:06:02,242 --> 00:06:04,200
ADAM POWELL: So if you've
been following along,

117
00:06:04,200 --> 00:06:06,616
you probably recognize some
similarities with the fragment

118
00:06:06,616 --> 00:06:07,950
API in this as well.

119
00:06:07,950 --> 00:06:10,850
So at this point we've got
these two different components.

120
00:06:10,850 --> 00:06:12,480
Which one do you use?

121
00:06:12,480 --> 00:06:14,870
Well, as the slides are
already spoiling for you,

122
00:06:14,870 --> 00:06:17,594
this really isn't an
either- or question.

123
00:06:17,594 --> 00:06:20,010
One of these things doesn't
necessarily replace the other.

124
00:06:20,010 --> 00:06:22,040
And here's why.

125
00:06:22,040 --> 00:06:25,830
Fragments, on one hand, that
everybody knows and loves,

126
00:06:25,830 --> 00:06:28,190
are statefully
managed and recreated

127
00:06:28,190 --> 00:06:32,030
after either a process death,
an activity recreation,

128
00:06:32,030 --> 00:06:35,630
or recreation of any hosts that
you have the fragment within.

129
00:06:35,630 --> 00:06:37,760
Fragments manage views
and also interact

130
00:06:37,760 --> 00:06:39,620
with the navigation
stack, which are

131
00:06:39,620 --> 00:06:42,230
things that are firmly out
of scope of what LifeCycle

132
00:06:42,230 --> 00:06:43,880
observers are meant to do.

133
00:06:43,880 --> 00:06:45,740
Instead, LifeCycle
observers are meant

134
00:06:45,740 --> 00:06:47,930
to enable more granular
factoring of your code,

135
00:06:47,930 --> 00:06:50,360
whether you're in an
activity or a fragment.

136
00:06:50,360 --> 00:06:51,110
They're stateless.

137
00:06:51,110 --> 00:06:53,570
So that means that they
must be registered each time

138
00:06:53,570 --> 00:06:54,770
the owner is recreated.

139
00:06:54,770 --> 00:06:56,186
We're not going
to try to recreate

140
00:06:56,186 --> 00:06:57,290
these magically for you.

141
00:06:57,290 --> 00:06:59,150
They don't have any
concept of instant state

142
00:06:59,150 --> 00:07:00,780
that they carry
around with them.

143
00:07:00,780 --> 00:07:02,510
So these are meant to be
very, very lightweight,

144
00:07:02,510 --> 00:07:04,968
so that you don't have a whole
lot of additional management

145
00:07:04,968 --> 00:07:06,170
overhead.

146
00:07:06,170 --> 00:07:09,470
And last, there's no relation
to the viewer navigation

147
00:07:09,470 --> 00:07:10,010
management.

148
00:07:10,010 --> 00:07:12,470
These really are meant
to be very tightly

149
00:07:12,470 --> 00:07:16,330
scoped, isolated components.

150
00:07:16,330 --> 00:07:17,950
So they can really
help everyone.

151
00:07:17,950 --> 00:07:21,040
It means that it's much
simpler to integrate libraries

152
00:07:21,040 --> 00:07:23,860
with your code, as long as
those libraries have provided

153
00:07:23,860 --> 00:07:26,124
LifeCycle observer
aware components.

154
00:07:26,124 --> 00:07:28,540
It means that you can break
up those really large fragment

155
00:07:28,540 --> 00:07:31,300
or activity classes to make
them much simpler to understand

156
00:07:31,300 --> 00:07:32,440
for a reader.

157
00:07:32,440 --> 00:07:35,200
And you can provide much
more granular guarantees

158
00:07:35,200 --> 00:07:38,660
around what operations are valid
at any given point in time.

159
00:07:38,660 --> 00:07:41,860
You can make it so that if
an operation happens then

160
00:07:41,860 --> 00:07:44,050
you're guaranteed to
be in a correct state

161
00:07:44,050 --> 00:07:45,130
when something is called.

162
00:07:45,130 --> 00:07:48,060


163
00:07:48,060 --> 00:07:50,685
So LifeCycle owner
as already introduced

164
00:07:50,685 --> 00:07:51,900
is just an interface.

165
00:07:51,900 --> 00:07:53,630
Anyone can implement this.

166
00:07:53,630 --> 00:07:55,680
This means that you
can improve testability

167
00:07:55,680 --> 00:07:56,802
by creating your own.

168
00:07:56,802 --> 00:07:59,010
You can create your own sort
of fragment-like library

169
00:07:59,010 --> 00:08:01,170
implementations if
you feel so inclined.

170
00:08:01,170 --> 00:08:03,330
But you can also create
composite life cycles.

171
00:08:03,330 --> 00:08:06,780
Life cycles that span across
other smaller lifecycle

172
00:08:06,780 --> 00:08:08,010
definitions.

173
00:08:08,010 --> 00:08:10,710
So you can answer questions
like, is my app visible?

174
00:08:10,710 --> 00:08:12,750
So this is a really
common composite lifecycle

175
00:08:12,750 --> 00:08:15,000
that many of you may
be interested in.

176
00:08:15,000 --> 00:08:17,160
It lets you do things
like session management

177
00:08:17,160 --> 00:08:19,530
to track a particular
session across perhaps

178
00:08:19,530 --> 00:08:23,100
some sort of a flow
or a series of logged

179
00:08:23,100 --> 00:08:24,870
in versus logged out events.

180
00:08:24,870 --> 00:08:29,020
And it may help you
with analytics as well.

181
00:08:29,020 --> 00:08:32,280
So we have the process LifeCycle
owner as kind of a component

182
00:08:32,280 --> 00:08:35,350
that I think a lot of you will
be interested in for this.

183
00:08:35,350 --> 00:08:39,058
It's the composite lifecycle of
all the activities in your app.

184
00:08:39,058 --> 00:08:41,009
So there's no configuration
changes to handle,

185
00:08:41,010 --> 00:08:44,440
because we're not going to be
dealing with those from these.

186
00:08:44,440 --> 00:08:46,350
The process LifeCycle
owner just stays

187
00:08:46,350 --> 00:08:48,000
alive through the whole process.

188
00:08:48,000 --> 00:08:50,041
But that also means that
you don't get state risk

189
00:08:50,041 --> 00:08:52,660
restoration after process death
like we mentioned earlier.

190
00:08:52,660 --> 00:08:54,600
So that means that
you don't have

191
00:08:54,600 --> 00:08:56,905
to handle saving and
restoring that state

192
00:08:56,905 --> 00:08:59,280
but at the same time, you need
to remember to re-register

193
00:08:59,280 --> 00:09:02,199
these process lifecycle-based
observers if that's something

194
00:09:02,199 --> 00:09:03,240
that you're working with.

195
00:09:03,240 --> 00:09:05,750


196
00:09:05,750 --> 00:09:09,110
So many indirect
components provide a lot

197
00:09:09,110 --> 00:09:11,330
of deep plumbing
layers for things

198
00:09:11,330 --> 00:09:13,790
that you can plug
into and work with.

199
00:09:13,790 --> 00:09:15,800
But a lot of times
we've kind of omitted

200
00:09:15,800 --> 00:09:17,720
the idea of higher
level components that

201
00:09:17,720 --> 00:09:20,210
make use of that plumbing
so that you can just plug

202
00:09:20,210 --> 00:09:21,280
play and go.

203
00:09:21,280 --> 00:09:24,300
So do we have anything more
high level than the bare events

204
00:09:24,300 --> 00:09:25,530
and states here?

205
00:09:25,530 --> 00:09:26,800
YIGIT BOYAR: Maybe we do.

206
00:09:26,800 --> 00:09:27,760
I will show you.

207
00:09:27,760 --> 00:09:28,870
ADAM POWELL: Great

208
00:09:28,870 --> 00:09:30,530
YIGIT BOYAR: Thanks, Adam.

209
00:09:30,530 --> 00:09:33,680
So it's so nice
now you can observe

210
00:09:33,680 --> 00:09:37,310
a LifeCycle is well-defined,
is a first class citizen.

211
00:09:37,310 --> 00:09:40,530
But you still need to
deal with these things.

212
00:09:40,530 --> 00:09:44,780
And we told like, there's
some common LifeCycle problems

213
00:09:44,780 --> 00:09:47,100
that we should be able to
solve with this component.

214
00:09:47,100 --> 00:09:48,860
So we'll look at the
problems that people

215
00:09:48,860 --> 00:09:51,740
are having, and
this was probably

216
00:09:51,740 --> 00:09:54,110
the most major problem
we've been seeing,

217
00:09:54,110 --> 00:09:56,320
the untimely UI updates.

218
00:09:56,320 --> 00:09:58,920
It's like your activity
receives a callback,

219
00:09:58,920 --> 00:10:00,530
but the activity's
already stopped.

220
00:10:00,530 --> 00:10:03,050
They tried to start a
new activity and crashes.

221
00:10:03,050 --> 00:10:06,010
Or it tries to add a
fragment and crashes.

222
00:10:06,010 --> 00:10:09,410
If an activity or a
fragment is stopped,

223
00:10:09,410 --> 00:10:12,317
there is no reason to
update that activity.

224
00:10:12,317 --> 00:10:13,400
You don't want to do that.

225
00:10:13,400 --> 00:10:16,190
If the activity happens to
become visible again, then

226
00:10:16,190 --> 00:10:17,480
you want to do it.

227
00:10:17,480 --> 00:10:20,480
So we realized that this
is a very common problem,

228
00:10:20,480 --> 00:10:23,990
and we wanted to solve this with
a higher level component which

229
00:10:23,990 --> 00:10:26,060
we call LiveData.

230
00:10:26,060 --> 00:10:29,780
When we look at the
LiveData in detail,

231
00:10:29,780 --> 00:10:32,840
it's actually an
observable data holder.

232
00:10:32,840 --> 00:10:35,180
It just holds on
to some information

233
00:10:35,180 --> 00:10:36,490
that you can observe.

234
00:10:36,490 --> 00:10:38,270
Now the difference
between LiveData

235
00:10:38,270 --> 00:10:41,225
and your other observables
in data mining or RxJava

236
00:10:41,225 --> 00:10:45,350
or whatever, is that
LiveData is LifeCycle aware.

237
00:10:45,350 --> 00:10:48,020
It knows about
Android life cycles,

238
00:10:48,020 --> 00:10:50,030
and when you want to
observe a LiveData,

239
00:10:50,030 --> 00:10:52,580
you can pass in this
LifeCycle so that it

240
00:10:52,580 --> 00:10:54,480
can manage your subscription.

241
00:10:54,480 --> 00:10:57,210
The nice thing about LiveData
that is that you observe,

242
00:10:57,210 --> 00:10:59,340
and that's all you do.

243
00:10:59,340 --> 00:11:00,860
So if we look at
the usage example,

244
00:11:00,860 --> 00:11:02,210
let's say we have an activity.

245
00:11:02,210 --> 00:11:04,110
We receive a LiveData
from somewhere.

246
00:11:04,110 --> 00:11:08,040
It doesn't really matter, and
now we call observe on it.

247
00:11:08,040 --> 00:11:10,160
And when we are
calling observe, we

248
00:11:10,160 --> 00:11:13,600
are passing this, which
is the LiveData owner.

249
00:11:13,600 --> 00:11:14,780
That's all you need to say.

250
00:11:14,780 --> 00:11:18,770
I want to observe this
LiveData within this LifeCycle.

251
00:11:18,770 --> 00:11:21,830
Which also means if
this LifeCycle is gone,

252
00:11:21,830 --> 00:11:23,150
I don't want to observe it.

253
00:11:23,150 --> 00:11:26,550
Or if this LifeCycle is stopped,
I don't want to receive events.

254
00:11:26,550 --> 00:11:30,466


255
00:11:30,466 --> 00:11:32,340
And then once you do
this, that's all you do.

256
00:11:32,340 --> 00:11:34,410
You don't need to
write onStart, onStop.

257
00:11:34,410 --> 00:11:37,870
We want Android to want
to look more like this.

258
00:11:37,870 --> 00:11:40,040
You initialze things as
more like find and forget.

259
00:11:40,040 --> 00:11:43,060
You initialize, and you're done.

260
00:11:43,060 --> 00:11:45,990
So let's look at what happens
when our activity starts

261
00:11:45,990 --> 00:11:47,910
observing that LiveData.

262
00:11:47,910 --> 00:11:52,560
So onCreate, it called observe,
it said LiveData is observable.

263
00:11:52,560 --> 00:11:54,630
And as soon as the
activity starts,

264
00:11:54,630 --> 00:11:56,470
it starts receiving
data changes.

265
00:11:56,470 --> 00:11:59,490
So whenever the
LiveData value changes,

266
00:11:59,490 --> 00:12:01,950
we displace that event
back to your observer

267
00:12:01,950 --> 00:12:03,530
inside the activity.

268
00:12:03,530 --> 00:12:05,450
It can also be a fragment.

269
00:12:05,450 --> 00:12:07,260
Let's say a user
decides to rotate

270
00:12:07,260 --> 00:12:09,090
the activity at this moment.

271
00:12:09,090 --> 00:12:11,540
So you know that the
activity will be stopped.

272
00:12:11,540 --> 00:12:13,320
And what happens
at the same time,

273
00:12:13,320 --> 00:12:16,110
the LiveData happens
to be updated.

274
00:12:16,110 --> 00:12:18,990
If that happens, we are not
going to tell the activity

275
00:12:18,990 --> 00:12:22,590
about this change because there
cannot be any reason for you

276
00:12:22,590 --> 00:12:27,210
to update the UI, because
it already stopped.

277
00:12:27,210 --> 00:12:29,640
Similarly, if the
activity is destroyed,

278
00:12:29,640 --> 00:12:31,980
we will automatically
remove that subscription

279
00:12:31,980 --> 00:12:34,320
because that activity is gone.

280
00:12:34,320 --> 00:12:36,990
There is no reason to
keep a reference back

281
00:12:36,990 --> 00:12:39,240
to that activity.

282
00:12:39,240 --> 00:12:41,010
Now we said the
activity was rotating,

283
00:12:41,010 --> 00:12:42,630
so you know that
Android is going

284
00:12:42,630 --> 00:12:44,880
to recreate that activity.

285
00:12:44,880 --> 00:12:48,270
And then we are observing
the same LiveData back.

286
00:12:48,270 --> 00:12:49,985
As soon as that
activity starts, it's

287
00:12:49,985 --> 00:12:53,190
going to receive
last available data.

288
00:12:53,190 --> 00:12:57,720
So your UI is going to have the
data before it gets a chance

289
00:12:57,720 --> 00:12:59,790
to draw.

290
00:12:59,790 --> 00:13:01,920
So similarly, I
say the user hits

291
00:13:01,920 --> 00:13:05,330
the Home button, which means
the activity will be stopped.

292
00:13:05,330 --> 00:13:08,700
Again, if the LiveData changes
while the activity is stopped,

293
00:13:08,700 --> 00:13:10,840
it's not going to
receive any events.

294
00:13:10,840 --> 00:13:14,010
Even if the data changes,
we are not going to tell it.

295
00:13:14,010 --> 00:13:17,280
But as soon as if the user
comes back to the application,

296
00:13:17,280 --> 00:13:19,510
we will give it the
last available data.

297
00:13:19,510 --> 00:13:22,990
So this is why we call LiveData
is not just a stream of events.

298
00:13:22,990 --> 00:13:26,910
It holds onto the data so
that if any observer comes,

299
00:13:26,910 --> 00:13:30,430
it receives the last
available value.

300
00:13:30,430 --> 00:13:33,620
And then eventually, the user
backs out of that activity,

301
00:13:33,620 --> 00:13:37,830
and then we remove
that subscription.

302
00:13:37,830 --> 00:13:40,730
You can also extend
the LiveData class.

303
00:13:40,730 --> 00:13:45,950
Because LiveData provides
two really handy callbacks.

304
00:13:45,950 --> 00:13:48,410
The first one is called
onactive which means

305
00:13:48,410 --> 00:13:50,930
you have an active observer.

306
00:13:50,930 --> 00:13:52,580
Another one is
called oninactive,

307
00:13:52,580 --> 00:13:54,370
which means you don't
have any observers,

308
00:13:54,370 --> 00:13:56,450
so don't bother
changing your value

309
00:13:56,450 --> 00:14:00,020
if it is something
that you care about.

310
00:14:00,020 --> 00:14:03,800
You probably ask now what
is an active observer?

311
00:14:03,800 --> 00:14:06,220
An active observer
is an observer

312
00:14:06,220 --> 00:14:09,680
whose attached LifeCycle
is started or resumed.

313
00:14:09,680 --> 00:14:12,890
So it's like a fragment that's
currently visible to the user.

314
00:14:12,890 --> 00:14:15,380
If the fragment is
on the back stack,

315
00:14:15,380 --> 00:14:16,660
the user is not seeing it.

316
00:14:16,660 --> 00:14:18,260
It stopped, so it's not active.

317
00:14:18,260 --> 00:14:22,430
There's no reason to do
any work for that fragment.

318
00:14:22,430 --> 00:14:24,850
Let's see how we can take
advantage of these named

319
00:14:24,850 --> 00:14:25,770
callbacks.

320
00:14:25,770 --> 00:14:28,270
We are going to create
a new location LiveData

321
00:14:28,270 --> 00:14:31,190
class, which presents
the location of something

322
00:14:31,190 --> 00:14:32,580
on the device.

323
00:14:32,580 --> 00:14:37,920
So we say this data holds
an instance of a location.

324
00:14:37,920 --> 00:14:40,460
In cross-sector, we just
get the location manager

325
00:14:40,460 --> 00:14:41,850
from the system service.

326
00:14:41,850 --> 00:14:43,670
There's nothing fancy here.

327
00:14:43,670 --> 00:14:47,210
We have a listener whenever
the system server sends us

328
00:14:47,210 --> 00:14:50,830
any location, we just
call setValue on us.

329
00:14:50,830 --> 00:14:51,530
This all you do.

330
00:14:51,530 --> 00:14:53,460
There is no LifeCycle
handling here.

331
00:14:53,460 --> 00:14:56,120
You just call setValue,
and LiveData takes

332
00:14:56,120 --> 00:14:57,710
care of handling the LifeCycle.

333
00:14:57,710 --> 00:15:00,080
And you may have any
number of observers.

334
00:15:00,080 --> 00:15:02,450
It doesn't really matter.

335
00:15:02,450 --> 00:15:04,850
So we want to override onactive.

336
00:15:04,850 --> 00:15:07,340
The very first active
observer comes.

337
00:15:07,340 --> 00:15:10,280
We want to start listening
to the system service.

338
00:15:10,280 --> 00:15:14,300
Similarly, when the last
active observer goes away,

339
00:15:14,300 --> 00:15:19,140
we want to stop observing
the system service.

340
00:15:19,140 --> 00:15:21,800
Now if you look at that
location LiveData class

341
00:15:21,800 --> 00:15:24,020
we just created in the
previous example, let's look

342
00:15:24,020 --> 00:15:26,210
at the properties of that class.

343
00:15:26,210 --> 00:15:28,100
First of all, it
is LifeCycle area.

344
00:15:28,100 --> 00:15:31,280
It knows when to start
itself, when to stop itself.

345
00:15:31,280 --> 00:15:34,340
You just don't need
to babysit it anymore.

346
00:15:34,340 --> 00:15:36,110
It is self-sufficient.

347
00:15:36,110 --> 00:15:37,140
You start it.

348
00:15:37,140 --> 00:15:39,480
You forget about it.

349
00:15:39,480 --> 00:15:40,470
It can be a singleton.

350
00:15:40,470 --> 00:15:42,620
Like all of the subscriptions
are automatically

351
00:15:42,620 --> 00:15:43,850
managed for you.

352
00:15:43,850 --> 00:15:47,090
So if the data is logically
singleton your codebase,

353
00:15:47,090 --> 00:15:50,030
you can make the LiveData
instance singleton.

354
00:15:50,030 --> 00:15:51,710
So there's this
thing where normally

355
00:15:51,710 --> 00:15:54,800
if you keep referencing
an activity or a fragment

356
00:15:54,800 --> 00:15:57,720
from a certain context,
that will be a big no no.

357
00:15:57,720 --> 00:16:00,350
But if you are using
LiveData it is yes yes,

358
00:16:00,350 --> 00:16:05,340
because we manage the
substitution for you.

359
00:16:05,340 --> 00:16:08,550
So you also don't need to
subclass LiveData all the time.

360
00:16:08,550 --> 00:16:10,910
So if you just need
an instance of it

361
00:16:10,910 --> 00:16:12,790
but you already
have the value, you

362
00:16:12,790 --> 00:16:14,990
could use this mutable
LiveData class,

363
00:16:14,990 --> 00:16:18,770
which comes inside the library
that has a public setter.

364
00:16:18,770 --> 00:16:21,170
But usually when you
are using this class,

365
00:16:21,170 --> 00:16:24,530
internally you will have
it but the API you expose

366
00:16:24,530 --> 00:16:26,360
will just return a
LiveData, because you

367
00:16:26,360 --> 00:16:28,370
don't want to expose
the fact that anyone

368
00:16:28,370 --> 00:16:31,470
can set the value on it.

369
00:16:31,470 --> 00:16:34,920
Now when we were designing
these LifeCycle components,

370
00:16:34,920 --> 00:16:38,730
the LiveData, see we
spent a lot of time

371
00:16:38,730 --> 00:16:41,380
to get rid of one exception.

372
00:16:41,380 --> 00:16:43,350
This fragment exception that I--

373
00:16:43,350 --> 00:16:50,520
[APPLAUSE]

374
00:16:50,520 --> 00:16:54,350
We really wanted to say, please,
no more fragment transaction

375
00:16:54,350 --> 00:16:55,460
exceptions.

376
00:16:55,460 --> 00:16:58,570
So LiveData guarantees that
if you received anywhere,

377
00:16:58,570 --> 00:17:00,910
you could run a
fragment transaction.

378
00:17:00,910 --> 00:17:05,310
And to see how we are making
it part of the history,

379
00:17:05,310 --> 00:17:10,118
I want to invite Adam
back to explain it to us.

380
00:17:10,118 --> 00:17:11,539
ADAM POWELL: All
right, so anyone

381
00:17:11,540 --> 00:17:13,205
who has received one
of these exceptions

382
00:17:13,205 --> 00:17:15,289
realizes that it
doesn't just come

383
00:17:15,290 --> 00:17:18,710
from trying to do something
when you just completely stopped

384
00:17:18,710 --> 00:17:20,348
and you absolutely know it.

385
00:17:20,348 --> 00:17:21,889
These exceptions
tend to come in when

386
00:17:21,890 --> 00:17:26,010
you get into very intricate,
nested life cycles.

387
00:17:26,010 --> 00:17:28,910
So we wanted to make sure to be
very thoughtful about defining

388
00:17:28,910 --> 00:17:34,190
how the LifeCycle observer
callbacks are invoked and when.

389
00:17:34,190 --> 00:17:37,400
So in a case like
this, what happens?

390
00:17:37,400 --> 00:17:42,120
You have defined handler
for the stop event.

391
00:17:42,120 --> 00:17:44,872
So in the container
your activity onStop,

392
00:17:44,872 --> 00:17:47,330
you want to make sure that you
don't get an onChanged event

393
00:17:47,330 --> 00:17:48,770
after the onStop has happened.

394
00:17:48,770 --> 00:17:52,660


395
00:17:52,660 --> 00:17:54,570
But in order for
that to happen, what

396
00:17:54,570 --> 00:17:56,490
needs to be true
about when we actually

397
00:17:56,490 --> 00:18:00,030
invoke all of the
onStop listeners

398
00:18:00,030 --> 00:18:02,610
that are attached
to these observers.

399
00:18:02,610 --> 00:18:05,770
So we have to define a
really strict order for this.

400
00:18:05,770 --> 00:18:09,420
So as we go through create
and start and onResume,

401
00:18:09,420 --> 00:18:11,940
we know that we need
to invoke the LifeCycle

402
00:18:11,940 --> 00:18:15,480
observers after the
container event happens.

403
00:18:15,480 --> 00:18:18,090
So you know in your
observer that everything

404
00:18:18,090 --> 00:18:20,461
about your LifeCycle
owner has been configured.

405
00:18:20,461 --> 00:18:21,960
If you check any
state about it, you

406
00:18:21,960 --> 00:18:25,397
know that you're already
completely in that state.

407
00:18:25,397 --> 00:18:27,480
But that means something
really special for coming

408
00:18:27,480 --> 00:18:29,470
back down the other direction.

409
00:18:29,470 --> 00:18:33,540
It means that when the activity
starts to become paused,

410
00:18:33,540 --> 00:18:34,995
you want your
LifeCycle observers

411
00:18:34,995 --> 00:18:36,870
to be able to shut down
anything that they're

412
00:18:36,870 --> 00:18:39,060
doing before the activity
does all of the work

413
00:18:39,060 --> 00:18:41,400
to actually become paused.

414
00:18:41,400 --> 00:18:42,810
Similar for stop.

415
00:18:42,810 --> 00:18:44,850
And this is where
this becomes really

416
00:18:44,850 --> 00:18:47,220
important for the fragment
transaction exception.

417
00:18:47,220 --> 00:18:49,260
You want to make
sure that you're

418
00:18:49,260 --> 00:18:52,440
recording, that you're fully
stopped before the fragment

419
00:18:52,440 --> 00:18:54,600
system goes through
and flags everything

420
00:18:54,600 --> 00:18:58,180
as being completely locked out.

421
00:18:58,180 --> 00:19:01,410
So what that means is that the
stop event of your LifeCycle

422
00:19:01,410 --> 00:19:04,770
observer will always be invoked
before the activity onStop

423
00:19:04,770 --> 00:19:10,710
or before the full stop event
for your container happens.

424
00:19:10,710 --> 00:19:13,260
So this seems really similar
to some other libraries

425
00:19:13,260 --> 00:19:15,480
that some people may
have seen in the past.

426
00:19:15,480 --> 00:19:16,600
Can you talk about that?

427
00:19:16,600 --> 00:19:22,530
SERGEI VASILINETC: Yes, when we
create new observable pattern,

428
00:19:22,530 --> 00:19:26,220
nowadays this question
is unavoidable.

429
00:19:26,220 --> 00:19:29,220
Is it another RxJava?

430
00:19:29,220 --> 00:19:32,490
And the answer to
this question is, yes,

431
00:19:32,490 --> 00:19:34,740
because we want to promote
a reactive programming

432
00:19:34,740 --> 00:19:37,980
model, especially when it
comes to the relationship

433
00:19:37,980 --> 00:19:40,710
between your UI and the
state [INAUDIBLE] UI.

434
00:19:40,710 --> 00:19:45,490
We want you to react on
the changes of the state.

435
00:19:45,490 --> 00:19:48,300
So it means that it's a
reactive programming model.

436
00:19:48,300 --> 00:19:51,000
But on the other hand, no.

437
00:19:51,000 --> 00:19:54,840
Because it's the LifeCycle
aware out of box,

438
00:19:54,840 --> 00:19:57,930
as Yigit mentioned,
and it's much easier.

439
00:19:57,930 --> 00:20:02,940
As many of you may know,
the learning curve of RxJava

440
00:20:02,940 --> 00:20:04,560
is super steep.

441
00:20:04,560 --> 00:20:08,850
And if you have an
Android learner curve,

442
00:20:08,850 --> 00:20:13,350
and after that we add RxJava
learning curve on top of it,

443
00:20:13,350 --> 00:20:16,050
it becomes very
hard to new people

444
00:20:16,050 --> 00:20:19,420
to start to develop
on our platform.

445
00:20:19,420 --> 00:20:25,890
So we can't just say to them,
oh let's go, just learn this,

446
00:20:25,890 --> 00:20:27,330
that's it. .

447
00:20:27,330 --> 00:20:32,310
No, but if you already
learned RxJava,

448
00:20:32,310 --> 00:20:37,020
we don't expect you to migrate
from it to our solution.

449
00:20:37,020 --> 00:20:41,280
Because you already
passed the learning curve,

450
00:20:41,280 --> 00:20:45,960
you and your coworkers are
comfortable with it, fine.

451
00:20:45,960 --> 00:20:48,190
We are totally fine with this.

452
00:20:48,190 --> 00:20:51,330
But one thing we ask
you to do is to be sure

453
00:20:51,330 --> 00:20:53,920
that you manage LifeCycle.

454
00:20:53,920 --> 00:20:58,210
RxJava has common
approaches to solve this.

455
00:20:58,210 --> 00:21:02,430
Be sure to use it and
everything will be fine.

456
00:21:02,430 --> 00:21:09,885
But when you start a new app,
I think this model is the best.

457
00:21:09,885 --> 00:21:15,010
The best is to start the project
with LiveData, because it's

458
00:21:15,010 --> 00:21:17,310
simpler, it's faster,
it's lightweight,

459
00:21:17,310 --> 00:21:20,270
it's well integrated
with a framework.

460
00:21:20,270 --> 00:21:24,970
And if you feel like you love
reacting programming a lot,

461
00:21:24,970 --> 00:21:28,480
you want to bring it
not only to relation

462
00:21:28,480 --> 00:21:31,930
between UI and the state.

463
00:21:31,930 --> 00:21:33,430
You want to bring
it to the business

464
00:21:33,430 --> 00:21:36,340
part of your application.

465
00:21:36,340 --> 00:21:41,070
Then you may consider
the addition of RxJava,

466
00:21:41,070 --> 00:21:44,230
because it gives you more power.

467
00:21:44,230 --> 00:21:47,140
And we will actually
help you to do that.

468
00:21:47,140 --> 00:21:51,790
We have this extension
to our library, which

469
00:21:51,790 --> 00:21:55,780
gives a possibility to create
LiveData from Publisher

470
00:21:55,780 --> 00:21:58,930
and create Publisher
from LiveData.

471
00:21:58,930 --> 00:22:03,970
So this integration
should be quite smooth.

472
00:22:03,970 --> 00:22:07,330
But I want to highlight a
key difference between RxJava

473
00:22:07,330 --> 00:22:08,080
and LiveData.

474
00:22:08,080 --> 00:22:11,980
So as Yigit already
said, LiveData

475
00:22:11,980 --> 00:22:13,870
is a holder and not a stream.

476
00:22:13,870 --> 00:22:17,320
So we have a reference
to the last value,

477
00:22:17,320 --> 00:22:20,290
and observers immediately
receive the last value when

478
00:22:20,290 --> 00:22:24,820
they start to observe LiveData.

479
00:22:24,820 --> 00:22:27,550
And now the big difference
is a threading model.

480
00:22:27,550 --> 00:22:31,840
As you know, RxJava has a very
sophisticated threading model.

481
00:22:31,840 --> 00:22:35,390
It's extremely powerful,
but in most cases,

482
00:22:35,390 --> 00:22:37,610
you probably don't need it.

483
00:22:37,610 --> 00:22:40,360
And we have everything
on the main thread.

484
00:22:40,360 --> 00:22:42,190
And the reason for
this is we want

485
00:22:42,190 --> 00:22:47,150
to give you all these guarantees
about when we will notify you

486
00:22:47,150 --> 00:22:50,740
about state changes.

487
00:22:50,740 --> 00:22:56,200
And we can't do this
on a background thread.

488
00:22:56,200 --> 00:22:58,330
We have just the one exception.

489
00:22:58,330 --> 00:23:00,850
We have a post
value method which

490
00:23:00,850 --> 00:23:03,720
just is a method
which trampoline value

491
00:23:03,720 --> 00:23:07,725
from a background thread to the
main thread and sets it there.

492
00:23:07,725 --> 00:23:08,770
It's super simple.

493
00:23:08,770 --> 00:23:11,400
So quick summary of what
we have at this point.

494
00:23:11,400 --> 00:23:13,870
LiveData events,
observable pattern

495
00:23:13,870 --> 00:23:16,460
which respects these events.

496
00:23:16,460 --> 00:23:20,090
But there is one big thing
which is not covered yet.

497
00:23:20,090 --> 00:23:23,590
And this is how to handle
onConfigurationChanges.

498
00:23:23,590 --> 00:23:28,690
In 2017, almost nine
years after Android

499
00:23:28,690 --> 00:23:32,050
was first time released, we
still discuss this question.

500
00:23:32,050 --> 00:23:34,090
And this is a totally
legit question.

501
00:23:34,090 --> 00:23:38,290
And we hear it constantly
from new Android developers.

502
00:23:38,290 --> 00:23:40,730
Many of you probably know
whats the deal with it.

503
00:23:40,730 --> 00:23:44,770
But let's take a look at
this oversimplified example,

504
00:23:44,770 --> 00:23:47,830
but it's still very vivid.

505
00:23:47,830 --> 00:23:50,050
So he wants to show
this information

506
00:23:50,050 --> 00:23:52,060
about user and your activity.

507
00:23:52,060 --> 00:23:54,830
And you want to make
some web service request.

508
00:23:54,830 --> 00:24:00,340
We will use LiveData to get
this result. It's super simple.

509
00:24:00,340 --> 00:24:02,800
When the request is just
started, it's empty.

510
00:24:02,800 --> 00:24:06,620
When the request
response is received,

511
00:24:06,620 --> 00:24:11,740
we put it to
LiveData as a value.

512
00:24:11,740 --> 00:24:14,070
And later we'll update our UI.

513
00:24:14,070 --> 00:24:19,917
We will notify the activity, and
it will do everything it needs.

514
00:24:19,917 --> 00:24:22,250
So what happens if the activity
is going to [INAUDIBLE].

515
00:24:22,250 --> 00:24:25,750
We're going to
make a call twice,

516
00:24:25,750 --> 00:24:28,560
and I hope that you don't
call web service right

517
00:24:28,560 --> 00:24:29,740
into your activity.

518
00:24:29,740 --> 00:24:33,670
But you probably have
some abstractions

519
00:24:33,670 --> 00:24:36,010
that does something
like that, which

520
00:24:36,010 --> 00:24:41,040
goes to a network, which goes
to caching and persistence

521
00:24:41,040 --> 00:24:43,030
storages.

522
00:24:43,030 --> 00:24:47,170
And all the separations
are synchronized by nature.

523
00:24:47,170 --> 00:24:51,070
So communication of these
components are synchronized.

524
00:24:51,070 --> 00:24:55,510
And you probably don't want to
make these calls twice anyway.

525
00:24:55,510 --> 00:24:58,060
So what you want
to do is to cache.

526
00:24:58,060 --> 00:25:01,470
This is our data,
like in our example.

527
00:25:01,470 --> 00:25:04,480
And what are the ways
today to do that?

528
00:25:04,480 --> 00:25:06,960
Well, one of a
proposed way to do it

529
00:25:06,960 --> 00:25:10,570
is a Fragment.setRetainInstance,
and Yigit

530
00:25:10,570 --> 00:25:12,340
can rant about this for hours.

531
00:25:12,340 --> 00:25:14,770
Unfortunately, we don't
have time for this today.

532
00:25:14,770 --> 00:25:17,600
But I just say that
the only effect

533
00:25:17,600 --> 00:25:19,900
that you have to run
fragment transaction

534
00:25:19,900 --> 00:25:22,400
is terrifying for
a lot of people.

535
00:25:22,400 --> 00:25:25,780
People go nuts and
another possible way

536
00:25:25,780 --> 00:25:29,960
to solve this is loaders, but
we don't fit here well as well.

537
00:25:29,960 --> 00:25:33,010
So we decided to tackle
this problem once again

538
00:25:33,010 --> 00:25:35,230
and create ViewModel.

539
00:25:35,230 --> 00:25:36,030
So what is this?

540
00:25:36,030 --> 00:25:39,070
ViewModel is an object
which is associated

541
00:25:39,070 --> 00:25:41,440
with a fragment or an
activity, but is retained

542
00:25:41,440 --> 00:25:43,750
during configuration changes.

543
00:25:43,750 --> 00:25:48,190
So its scope is a kind of a
logical scope of your activity.

544
00:25:48,190 --> 00:25:51,300
So what does this mean?

545
00:25:51,300 --> 00:25:51,900
Let's see.

546
00:25:51,900 --> 00:25:54,220
If we have access time and
the current moment, and we

547
00:25:54,220 --> 00:25:55,540
can predict the future.

548
00:25:55,540 --> 00:25:57,670
And we know that activity
is going to be created,

549
00:25:57,670 --> 00:25:59,390
and this means that
all construction

550
00:25:59,390 --> 00:26:01,690
events are going to happen.

551
00:26:01,690 --> 00:26:05,440
During onCreate we will request
ViewModel for the first time.

552
00:26:05,440 --> 00:26:07,780
We will create it, and
after that this activity

553
00:26:07,780 --> 00:26:10,850
just uses this ViewModel.

554
00:26:10,850 --> 00:26:12,220
Very simple.

555
00:26:12,220 --> 00:26:16,060
Now we predict that the
activity is going to be rotated.

556
00:26:16,060 --> 00:26:20,700
Let's see what's going to
happen with our ViewModel.

557
00:26:20,700 --> 00:26:27,400
We will receive events,
onPause, onStop, and onDestroy.

558
00:26:27,400 --> 00:26:30,880
But when all the
segments are cured

559
00:26:30,880 --> 00:26:34,090
and your activity is
destroyed, it's thrown away

560
00:26:34,090 --> 00:26:38,210
and is garbage collected,
ViewModel survived it.

561
00:26:38,210 --> 00:26:42,070
And the new activity, which was
created in place the old one

562
00:26:42,070 --> 00:26:44,510
uses the same, old object.

563
00:26:44,510 --> 00:26:48,520
So you can easily cache
there LiveData as we want to

564
00:26:48,520 --> 00:26:50,690
or something else.

565
00:26:50,690 --> 00:26:52,720
The last case, what
is going to happen

566
00:26:52,720 --> 00:26:55,600
if you have finished goal?

567
00:26:55,600 --> 00:26:58,280
Once again, we will receive
these destruction events,

568
00:26:58,280 --> 00:27:01,570
but this time,
ViewModel is available

569
00:27:01,570 --> 00:27:03,130
until onDestroy method.

570
00:27:03,130 --> 00:27:08,340
During onDestroy method, we
will call onClear on this.

571
00:27:08,340 --> 00:27:11,860
Which notifies you if you have
any currently running actions

572
00:27:11,860 --> 00:27:15,610
or any resources
its time to close.

573
00:27:15,610 --> 00:27:18,900
And after that, it's
going to be destroyed

574
00:27:18,900 --> 00:27:20,150
and garbage collected as well.

575
00:27:20,150 --> 00:27:24,310
So at the point when your
activity is destroyed,

576
00:27:24,310 --> 00:27:27,340
it's not going to be
recreated it again.

577
00:27:27,340 --> 00:27:30,980
Your ViewModel is gone as well.

578
00:27:30,980 --> 00:27:37,970
So let's quickly make
our sample in ViewModel.

579
00:27:37,970 --> 00:27:40,900
So it starts with
instantiating-- with creation

580
00:27:40,900 --> 00:27:43,270
of ViewModel class.

581
00:27:43,270 --> 00:27:47,860
We want to cache for user data
to create a fill for that.

582
00:27:47,860 --> 00:27:50,680
We agree our activity needs
to access this LiveData,

583
00:27:50,680 --> 00:27:52,450
so we create a getter for this.

584
00:27:52,450 --> 00:27:55,960
And finally, getter is
extremely straightforward.

585
00:27:55,960 --> 00:27:59,530
If we already requested the
data, we just return it.

586
00:27:59,530 --> 00:28:04,780
If the data is now, we'll
request it from a web service

587
00:28:04,780 --> 00:28:06,580
and return it.

588
00:28:06,580 --> 00:28:07,422
Fine.

589
00:28:07,422 --> 00:28:08,880
We had [INAUDIBLE]
on our activity.

590
00:28:08,880 --> 00:28:12,580
Now we need to get this
LiveData from ViewModel.

591
00:28:12,580 --> 00:28:18,370
To get it, we need to create
to get ViewModel somehow.

592
00:28:18,370 --> 00:28:19,450
So this is how we do it.

593
00:28:19,450 --> 00:28:21,970
Let's take a precise look at it.

594
00:28:21,970 --> 00:28:25,000
First of all, we need to get
ViewModel provider object.

595
00:28:25,000 --> 00:28:27,250
This is an object
which is associated

596
00:28:27,250 --> 00:28:28,570
with a fragment or an activity.

597
00:28:28,570 --> 00:28:34,270
It knows how to get already
existing ViewModel from it

598
00:28:34,270 --> 00:28:36,740
or how to create a new one.

599
00:28:36,740 --> 00:28:39,250
If there is no
existing ViewModel.

600
00:28:39,250 --> 00:28:44,650
After that, we request
our myActivity ViewModel,

601
00:28:44,650 --> 00:28:48,617
and later everything
is quite simple.

602
00:28:48,617 --> 00:28:49,450
We get the userData.

603
00:28:49,450 --> 00:28:54,730
We observe it to update the UI.

604
00:28:54,730 --> 00:28:59,860
So what are the rules
of usage of ViewModel?

605
00:28:59,860 --> 00:29:04,660
So ViewModel manages
the data for the UI.

606
00:29:04,660 --> 00:29:08,290
It means that it
speaks with business

607
00:29:08,290 --> 00:29:11,510
parts of your application
to retrieve the data.

608
00:29:11,510 --> 00:29:15,470
So it may be a repository
pattern or any other pattern

609
00:29:15,470 --> 00:29:17,890
that they use.

610
00:29:17,890 --> 00:29:22,450
It also, it's for its
user modifications

611
00:29:22,450 --> 00:29:24,140
back to these components.

612
00:29:24,140 --> 00:29:26,720
And now a good
case for ViewModel

613
00:29:26,720 --> 00:29:30,730
is acting as a communication
layer between fragments

614
00:29:30,730 --> 00:29:32,530
in one activity.

615
00:29:32,530 --> 00:29:36,490
And Yigit will speak
about this later.

616
00:29:36,490 --> 00:29:40,840
But prior to this,
things that you must not

617
00:29:40,840 --> 00:29:42,560
do in your ViewModel.

618
00:29:42,560 --> 00:29:46,580
So first of all,
you must not access

619
00:29:46,580 --> 00:29:51,870
views and any other
UI- related entities.

620
00:29:51,870 --> 00:29:54,670
The reason for
that, they are going

621
00:29:54,670 --> 00:29:57,010
to be created during
configuration change.

622
00:29:57,010 --> 00:30:02,400
If you try to use them, you will
ever use stale data from there,

623
00:30:02,400 --> 00:30:05,250
ever to leak them.

624
00:30:05,250 --> 00:30:09,230
That's going to finish bad.

625
00:30:09,230 --> 00:30:12,280
And it's fragmented
or activity's job

626
00:30:12,280 --> 00:30:17,110
to bind the data which you
will get from a ViewModel

627
00:30:17,110 --> 00:30:21,260
with actual UI,
text use, buttons.

628
00:30:21,260 --> 00:30:23,190
I don't know what else.

629
00:30:23,190 --> 00:30:26,590
And one more thing,
there are sources

630
00:30:26,590 --> 00:30:31,120
which sound more harmless
like strings or drawable,

631
00:30:31,120 --> 00:30:33,790
and you may think,
I may cash it here.

632
00:30:33,790 --> 00:30:38,020
No, they depend on current
configuration state of state

633
00:30:38,020 --> 00:30:38,800
as well.

634
00:30:38,800 --> 00:30:43,360
So yes, right now you may
have just one resource

635
00:30:43,360 --> 00:30:46,540
for every configuration,
but later, you

636
00:30:46,540 --> 00:30:49,870
will add in the same resource
for a different configuration.

637
00:30:49,870 --> 00:30:54,010
You will easily forget
to update your ViewModel.

638
00:30:54,010 --> 00:30:58,540
And you may not notice
this, but your users

639
00:30:58,540 --> 00:31:00,250
will see the invalid UI.

640
00:31:00,250 --> 00:31:02,230
And this is just ugly.

641
00:31:02,230 --> 00:31:06,970
And now Yigit will speak about
Inter Fragment communications.

642
00:31:06,970 --> 00:31:10,510


643
00:31:10,510 --> 00:31:12,270
YIGIT BOYAR: So I
want to talk about one

644
00:31:12,270 --> 00:31:16,050
of my favorite features
about ViewModel,

645
00:31:16,050 --> 00:31:19,020
which is communicating
between multiple fragments

646
00:31:19,020 --> 00:31:21,980
of the same activity.

647
00:31:21,980 --> 00:31:25,200
It's good that UI like this,
like the Gmail on the tablet

648
00:31:25,200 --> 00:31:29,500
where on the left side you pick
an email and on the right side,

649
00:31:29,500 --> 00:31:31,860
it shows the contents
of the email.

650
00:31:31,860 --> 00:31:34,560
Now usually you will
implement this as a fragment

651
00:31:34,560 --> 00:31:37,940
on the left which picks
something from the list,

652
00:31:37,940 --> 00:31:39,780
and another fragment
on the right, which

653
00:31:39,780 --> 00:31:42,960
shows how to show the
contents of an email

654
00:31:42,960 --> 00:31:45,330
so that if you're on the
phone you can reuse the same

655
00:31:45,330 --> 00:31:48,150
fragments but separate
from each other.

656
00:31:48,150 --> 00:31:52,170
Now if you ever tried to write
a UI like this, if you ever

657
00:31:52,170 --> 00:31:55,105
tried to make these two
fragments talk to each other,

658
00:31:55,105 --> 00:31:56,220
it's a pain in the neck.

659
00:31:56,220 --> 00:31:57,240
It's very, very hard.

660
00:31:57,240 --> 00:31:59,510
Like you need to
create an interface.

661
00:31:59,510 --> 00:32:01,530
But then what if
one fragment gets

662
00:32:01,530 --> 00:32:03,540
created before the other one.

663
00:32:03,540 --> 00:32:05,940
An activity needs to
talk to each other.

664
00:32:05,940 --> 00:32:07,931
Or like when the
activities are restored,

665
00:32:07,931 --> 00:32:09,430
you don't really
know which fragment

666
00:32:09,430 --> 00:32:11,340
will be restored first.

667
00:32:11,340 --> 00:32:14,880
It is really hard to
manage this state.

668
00:32:14,880 --> 00:32:21,020
But we can actually solve this
very elegantly using ViewModel.

669
00:32:21,020 --> 00:32:23,930
So let's say so these two
families actually want

670
00:32:23,930 --> 00:32:26,390
to talk about a selected email.

671
00:32:26,390 --> 00:32:29,060
This is the information
they want to share.

672
00:32:29,060 --> 00:32:30,950
So let's put it
inside a ViewModel

673
00:32:30,950 --> 00:32:33,920
and we are going to call
this shared ViewModel.

674
00:32:33,920 --> 00:32:36,130
So it has a mutable
LiveData inside it

675
00:32:36,130 --> 00:32:41,430
which you call selected, and it
provides two very simple APIs.

676
00:32:41,430 --> 00:32:45,410
The first one says, set the
select email to this email.

677
00:32:45,410 --> 00:32:49,610
Another one says, get the
selected email as a LiveData.

678
00:32:49,610 --> 00:32:52,510
It's a really simple ViewModel.

679
00:32:52,510 --> 00:32:56,030
But now once we have this,
let's go back to our fragments

680
00:32:56,030 --> 00:32:58,260
and see how we can use this.

681
00:32:58,260 --> 00:33:00,920
So inside the content
fragment, which is the one

682
00:33:00,920 --> 00:33:03,650
that wants to display the
contents of the email.

683
00:33:03,650 --> 00:33:07,550
It wants to know when the
selected email changes.

684
00:33:07,550 --> 00:33:09,930
So we're going to go-- so
we have already seen this.

685
00:33:09,930 --> 00:33:12,470
You can go to ViewModel
providers class

686
00:33:12,470 --> 00:33:15,230
and get the ViewModel
providers of this fragment.

687
00:33:15,230 --> 00:33:19,170
But we actually want ViewModel
not from this fragment,

688
00:33:19,170 --> 00:33:21,330
we want it from our activity.

689
00:33:21,330 --> 00:33:25,480
So all you have to do tell it
to do it from your activity.

690
00:33:25,480 --> 00:33:28,520
Now it's going to return your
ViewModel in the activity

691
00:33:28,520 --> 00:33:33,140
scope, and I will say, get
for the shared ViewModel.

692
00:33:33,140 --> 00:33:35,770
Now, the very first time one
of the fragments called this,

693
00:33:35,770 --> 00:33:37,460
we are going to
create a new one.

694
00:33:37,460 --> 00:33:39,520
When the other
fragment comes alive,

695
00:33:39,520 --> 00:33:42,830
it's going to receive the
same ViewModel instance.

696
00:33:42,830 --> 00:33:44,100
And I will do the same thing.

697
00:33:44,100 --> 00:33:46,650
So this one says, get
the selected email.

698
00:33:46,650 --> 00:33:48,662
Start observing on it.

699
00:33:48,662 --> 00:33:50,540
Really similarly, in
the select fragment

700
00:33:50,540 --> 00:33:54,500
which was the one on the
left by user pics and email,

701
00:33:54,500 --> 00:33:57,410
we get the same ViewModel.

702
00:33:57,410 --> 00:34:00,680
And whenever the user selects
an email from the list,

703
00:34:00,680 --> 00:34:03,080
we just call the
ViewModel- related method

704
00:34:03,080 --> 00:34:05,120
to change the selected email.

705
00:34:05,120 --> 00:34:08,239
Now these two fragments
talking to each other

706
00:34:08,239 --> 00:34:10,710
without actually
talking to each other.

707
00:34:10,710 --> 00:34:13,730
How does this really happen?

708
00:34:13,730 --> 00:34:15,380
So if we go back to our UI.

709
00:34:15,380 --> 00:34:18,679
So we have the selector on the
left, the content on the right.

710
00:34:18,679 --> 00:34:21,320
But if you look at the
details, actually both of these

711
00:34:21,320 --> 00:34:23,060
are talking to a
shared ViewModel.

712
00:34:23,060 --> 00:34:25,040
They never talk to each other.

713
00:34:25,040 --> 00:34:28,580
The video of this solution is
that if you're on the phone,

714
00:34:28,580 --> 00:34:31,280
let's say one fragment
replaces the other one,

715
00:34:31,280 --> 00:34:33,080
there's no room for error.

716
00:34:33,080 --> 00:34:35,270
Like the fragment still
talks to a ViewModel.

717
00:34:35,270 --> 00:34:37,370
ViewModels always that
nothing will crash.

718
00:34:37,370 --> 00:34:39,770
They don't even care
the other one is there.

719
00:34:39,770 --> 00:34:42,810


720
00:34:42,810 --> 00:34:45,349
Okay, so this is a
lot of information,

721
00:34:45,349 --> 00:34:47,670
and there's further
details about how

722
00:34:47,670 --> 00:34:49,170
these life cycles work.

723
00:34:49,170 --> 00:34:51,330
We really spent a
lot of time to make

724
00:34:51,330 --> 00:34:55,260
these handle most common
used cases on Android.

725
00:34:55,260 --> 00:34:58,620
So we come in just
the first trade out.

726
00:34:58,620 --> 00:35:03,150
You could try it
now, in [INAUDIBLE].

727
00:35:03,150 --> 00:35:05,850
Please check out all of the
architecture components.

728
00:35:05,850 --> 00:35:08,640
These are things that actually
work very well together.

729
00:35:08,640 --> 00:35:11,070
We have an architecture
guide which shows you

730
00:35:11,070 --> 00:35:15,330
how to use these things together
to write a good application.

731
00:35:15,330 --> 00:35:16,980
And also check our code labs.

732
00:35:16,980 --> 00:35:20,490
We have code lab sections that
will give you a first glimpse

733
00:35:20,490 --> 00:35:23,841
of how LifeCycles work.

734
00:35:23,841 --> 00:35:24,340
Thank you

735
00:35:24,340 --> 00:35:26,815
[APPLAUSE]

736
00:35:26,815 --> 00:35:29,055
[MUSIC PLAYING]

737
00:35:29,055 --> 00:00:00,000


1
00:00:00,000 --> 00:00:06,201
[ИГРАЕТ МУЗЫКА]

2
00:00:06,201 --> 00:00:09,380
СЕРГЕЙ ВАСИЛИНЕЦ:
Доброе утро всем!.

3
00:00:09,380 --> 00:00:10,130
Меня зовут Сергей

4
00:00:10,130 --> 00:00:12,620
Это Adam и Yigit,
они сегодня со мной,

5
00:00:12,620 --> 00:00:15,780
и мы поговорим о проблемах
жизненного цикла.

6
00:00:15,780 --> 00:00:21,240
Возможно, многие из вас
присутствовали вчера,

7
00:00:21,240 --> 00:00:24,670
когда Yigit представил новые
архитектурные компоненты.

8
00:00:24,670 --> 00:00:27,550
Он представил LiveData,
ViewModel, новую ORM

9
00:00:27,550 --> 00:00:28,540
называемую Room.

10
00:00:28,540 --> 00:00:31,900
И сегодня мы будем говорить
о жизненном цикле из

11
00:00:31,900 --> 00:00:34,990
парадигмы архитектурных
компонентов.

12
00:00:34,990 --> 00:00:37,715
Поэтому мы снова поговорим о
LiveData и ViewModel.

13
00:00:37,715 --> 00:00:41,140
Мы поговорим о преимуществах
жизненного цикла и о том, на каких

14
00:00:41,140 --> 00:00:45,210
библиотеках он основывается.

15
00:00:45,210 --> 00:00:49,150
Но мы затронем много деталей.

16
00:00:49,150 --> 00:00:51,890
У нас будут некоторые аргументы
в пользу наших решений.

17
00:00:51,890 --> 00:00:56,360
И, если вы были на вчерашней сессии,
вам будет все еще интересно.

18
00:00:56,360 --> 00:00:57,900
Но даже если вы не
присутствовали вчера, мы

19
00:00:57,900 --> 00:00:59,600
заново расскажем обо
всех этих вещах

20
00:00:59,600 --> 00:01:03,370
так что вам будет
все понятно.

21
00:01:03,370 --> 00:01:07,480
Ну, давайте посмотрим что у нас есть.

22
00:01:07,480 --> 00:01:11,280
Сегодня у нас Activity
по частям.

23
00:01:11,280 --> 00:01:14,300
Я начну стого, что
длинно, но с того, где

24
00:01:14,300 --> 00:01:17,330
десятки и десятки строк.

25
00:01:17,330 --> 00:01:22,190
И эти строки результат очень
естественного процесса.

26
00:01:22,190 --> 00:01:24,690
Сервисы Google play
попросили зарегистрировать их

27
00:01:24,690 --> 00:01:25,670
в onStart методах.

28
00:01:25,670 --> 00:01:29,620
Ваши компоненты должны знать
о событиях жизненного цикла,

29
00:01:29,620 --> 00:01:34,640
поэтому вам нужно получить их
в каком-либо API.

30
00:01:34,640 --> 00:01:38,100
И соответственно,
в onStop методе,

31
00:01:38,100 --> 00:01:42,530
вы должны вызвать все
методы-остановки,

32
00:01:42,530 --> 00:01:44,900
и тогда очень легко
забыть о каком-либо из них.

33
00:01:44,900 --> 00:01:46,880
И в результате утечка.

34
00:01:46,880 --> 00:01:51,950
И это приведет к растрате
батареи пользователя,

35
00:01:51,950 --> 00:01:54,920
и ваше приложение понравится
ему немного меньше.

36
00:01:54,920 --> 00:01:58,190
И это, возможно, нормально для них,
но мы не думаем, что это хорошо.

37
00:01:58,190 --> 00:02:02,180
И они думают, что ответ
в этой ситуации - это

38
00:02:02,180 --> 00:02:04,130
представление жизненного цикла
осведомленным о компонентах.

39
00:02:04,130 --> 00:02:06,770
Компоненты, которые взаимодействуют
с жизненным циклом.

40
00:02:06,770 --> 00:02:08,538
И первый щаг в этом r> направлении - представление

41
00:02:08,538 --> 00:02:11,750
жизненного цикла как
объекта первого класса.

42
00:02:11,750 --> 00:02:13,550
Итак, это очень простой
объект, который отвечает на

43
00:02:13,550 --> 00:02:17,370
вопрос, какое
состояние сейчас?

44
00:02:17,370 --> 00:02:19,130
И уведомляет вас о
новых событиях. И тогда

45
00:02:19,130 --> 00:02:22,340
никакая особенность не важна
но звучит нелепо прямо сейчас,

46
00:02:22,340 --> 00:02:26,060
события и состояния -
разные вещи.

47
00:02:26,060 --> 00:02:28,540
Вот, что я имею в виду.

48
00:02:28,540 --> 00:02:31,610
Ваша Activity создается в
инициализированном состоянии.

49
00:02:31,610 --> 00:02:37,965
И все этапы создания
проходят очень регулярно.

50
00:02:37,965 --> 00:02:39,680
OnCreate(), создание состояния.

51
00:02:39,680 --> 00:02:42,460
OnStart, старт состояния,
то же самое для resume.

52
00:02:42,460 --> 00:02:45,070
Но дорога назад немного
более интересная.

53
00:02:45,070 --> 00:02:48,920
So onPause event, leads
you from a resume state

54
00:02:48,920 --> 00:02:50,480
back to a starting state.

55
00:02:50,480 --> 00:02:53,490
Not some new pause state,
or something like that.

56
00:02:53,490 --> 00:02:57,870
And the reason for this is
from a system perspective,

57
00:02:57,870 --> 00:03:01,880
the states after onPause event
and onStart event are the same

58
00:03:01,880 --> 00:03:05,790
because the sets of the actions
that you are allowed to do

59
00:03:05,790 --> 00:03:07,010
is the same.

60
00:03:07,010 --> 00:03:11,960
And the same is true for
onStop and Creative state.

61
00:03:11,960 --> 00:03:14,350
And last event is onDestroy.

62
00:03:14,350 --> 00:03:18,390
It's pretty straightforward.

63
00:03:18,390 --> 00:03:20,150
It brings it to destroy state.

64
00:03:20,150 --> 00:03:21,730
Your activity is destroyed.

65
00:03:21,730 --> 00:03:25,720
It's going to be thrown
away and garbage collected.

66
00:03:25,720 --> 00:03:28,020
So let's make our
component LifeCycle aware.

67
00:03:28,020 --> 00:03:29,390
That's super straightforward.

68
00:03:29,390 --> 00:03:32,780
We take it with LifeCycle
observer interface,

69
00:03:32,780 --> 00:03:34,350
accepted interface.

70
00:03:34,350 --> 00:03:40,320
To get the actual events, we add
annotation and pass the events

71
00:03:40,320 --> 00:03:43,200
that we are interested in,
you can pass multiple events

72
00:03:43,200 --> 00:03:43,950
if you want to.

73
00:03:43,950 --> 00:03:48,180
The last step is to add
ourselves as an observer.

74
00:03:48,180 --> 00:03:53,910
And we may have a
potential problem here.

75
00:03:53,910 --> 00:03:57,810
What if the activity is
already started at this point?

76
00:03:57,810 --> 00:04:02,730
Does this mean that we are
going to receive onStop event,

77
00:04:02,730 --> 00:04:05,970
and and we didn't
receive onStart.

78
00:04:05,970 --> 00:04:09,540
And our component probably
is not ready for this.

79
00:04:09,540 --> 00:04:12,570
But it took care
of it, and we bring

80
00:04:12,570 --> 00:04:14,412
the observer to correct state.

81
00:04:14,412 --> 00:04:15,370
So what does this mean?

82
00:04:15,370 --> 00:04:17,670
Let's take this example,
which I just discussed.

83
00:04:17,670 --> 00:04:20,610
From activity perspective
onStart and onCreate

84
00:04:20,610 --> 00:04:26,250
create already happened, and
after that we add an observer.

85
00:04:26,250 --> 00:04:31,740
But observer will still receive
onCreate and onStart events

86
00:04:31,740 --> 00:04:34,950
immediately when
they were registered.

87
00:04:34,950 --> 00:04:38,130
So let's take one step further.

88
00:04:38,130 --> 00:04:39,870
OnResume, same situation.

89
00:04:39,870 --> 00:04:41,400
Resume state will
bring to resume

90
00:04:41,400 --> 00:04:45,550
state we got an onResume
event in addition to onCreate

91
00:04:45,550 --> 00:04:46,610
and onStart.

92
00:04:46,610 --> 00:04:48,660
A bit more
interesting situation,

93
00:04:48,660 --> 00:04:54,590
onPause In this situation, we
are in a start state as well as

94
00:04:54,590 --> 00:04:55,830
we learned.

95
00:04:55,830 --> 00:04:59,060
So we bring the oberserver
to the correct state

96
00:04:59,060 --> 00:05:00,030
which is start.

97
00:05:00,030 --> 00:05:04,040
So it's a similar situation
as we had one minute ago.

98
00:05:04,040 --> 00:05:06,930
Observer will receive
onCreate and onStart events,

99
00:05:06,930 --> 00:05:09,090
and that's it.

100
00:05:09,090 --> 00:05:13,460
So we don't have a
problem in this code.

101
00:05:13,460 --> 00:05:17,240
So how to get this
magical lifecycle object?

102
00:05:17,240 --> 00:05:20,940
We have this interface
which is super simple,

103
00:05:20,940 --> 00:05:25,060
but this probably doesn't
help much right now.

104
00:05:25,060 --> 00:05:26,580
And the actual
question is who are

105
00:05:26,580 --> 00:05:29,600
LifeCycle owners out of box.

106
00:05:29,600 --> 00:05:34,310
And the answer in this question
is support library fragments

107
00:05:34,310 --> 00:05:35,630
and support activities.

108
00:05:35,630 --> 00:05:40,140
But unfortunately, this is
true only in the bright future.

109
00:05:40,140 --> 00:05:44,300
And right now we have
LifeCycle activity

110
00:05:44,300 --> 00:05:46,040
and LifeCycle fragment.

111
00:05:46,040 --> 00:05:49,520
But at the point
of 1.0 release, we

112
00:05:49,520 --> 00:05:53,720
will merge our library to
support libraries so you

113
00:05:53,720 --> 00:05:56,070
don't have to use them later.

114
00:05:56,070 --> 00:05:59,400
And now Adam will speak
about some key differences

115
00:05:59,400 --> 00:06:02,242
between fragment and
LifeCyle observers

116
00:06:02,242 --> 00:06:04,200
ADAM POWELL: So if you've
been following along,

117
00:06:04,200 --> 00:06:06,616
you probably recognize some
similarities with the fragment

118
00:06:06,616 --> 00:06:07,950
API in this as well.

119
00:06:07,950 --> 00:06:10,850
So at this point we've got
these two different components.

120
00:06:10,850 --> 00:06:12,480
Which one do you use?

121
00:06:12,480 --> 00:06:14,870
Well, as the slides are
already spoiling for you,

122
00:06:14,870 --> 00:06:17,594
this really isn't an
either- or question.

123
00:06:17,594 --> 00:06:20,010
One of these things doesn't
necessarily replace the other.

124
00:06:20,010 --> 00:06:22,040
And here's why.

125
00:06:22,040 --> 00:06:25,830
Fragments, on one hand, that
everybody knows and loves,

126
00:06:25,830 --> 00:06:28,190
are statefully
managed and recreated

127
00:06:28,190 --> 00:06:32,030
after either a process death,
an activity recreation,

128
00:06:32,030 --> 00:06:35,630
or recreation of any hosts that
you have the fragment within.

129
00:06:35,630 --> 00:06:37,760
Fragments manage views
and also interact

130
00:06:37,760 --> 00:06:39,620
with the navigation
stack, which are

131
00:06:39,620 --> 00:06:42,230
things that are firmly out
of scope of what LifeCycle

132
00:06:42,230 --> 00:06:43,880
observers are meant to do.

133
00:06:43,880 --> 00:06:45,740
Instead, LifeCycle
observers are meant

134
00:06:45,740 --> 00:06:47,930
to enable more granular
factoring of your code,

135
00:06:47,930 --> 00:06:50,360
whether you're in an
activity or a fragment.

136
00:06:50,360 --> 00:06:51,110
They're stateless.

137
00:06:51,110 --> 00:06:53,570
So that means that they
must be registered each time

138
00:06:53,570 --> 00:06:54,770
the owner is recreated.

139
00:06:54,770 --> 00:06:56,186
We're not going
to try to recreate

140
00:06:56,186 --> 00:06:57,290
these magically for you.

141
00:06:57,290 --> 00:06:59,150
They don't have any
concept of instant state

142
00:06:59,150 --> 00:07:00,780
that they carry
around with them.

143
00:07:00,780 --> 00:07:02,510
So these are meant to be
very, very lightweight,

144
00:07:02,510 --> 00:07:04,968
so that you don't have a whole
lot of additional management

145
00:07:04,968 --> 00:07:06,170
overhead.

146
00:07:06,170 --> 00:07:09,470
And last, there's no relation
to the viewer navigation

147
00:07:09,470 --> 00:07:10,010
management.

148
00:07:10,010 --> 00:07:12,470
These really are meant
to be very tightly

149
00:07:12,470 --> 00:07:16,330
scoped, isolated components.

150
00:07:16,330 --> 00:07:17,950
So they can really
help everyone.

151
00:07:17,950 --> 00:07:21,040
It means that it's much
simpler to integrate libraries

152
00:07:21,040 --> 00:07:23,860
with your code, as long as
those libraries have provided

153
00:07:23,860 --> 00:07:26,124
LifeCycle observer
aware components.

154
00:07:26,124 --> 00:07:28,540
It means that you can break
up those really large fragment

155
00:07:28,540 --> 00:07:31,300
or activity classes to make
them much simpler to understand

156
00:07:31,300 --> 00:07:32,440
for a reader.

157
00:07:32,440 --> 00:07:35,200
And you can provide much
more granular guarantees

158
00:07:35,200 --> 00:07:38,660
around what operations are valid
at any given point in time.

159
00:07:38,660 --> 00:07:41,860
You can make it so that if
an operation happens then

160
00:07:41,860 --> 00:07:44,050
you're guaranteed to
be in a correct state

161
00:07:44,050 --> 00:07:45,130
when something is called.

162
00:07:45,130 --> 00:07:48,060


163
00:07:48,060 --> 00:07:50,685
So LifeCycle owner
as already introduced

164
00:07:50,685 --> 00:07:51,900
is just an interface.

165
00:07:51,900 --> 00:07:53,630
Anyone can implement this.

166
00:07:53,630 --> 00:07:55,680
This means that you
can improve testability

167
00:07:55,680 --> 00:07:56,802
by creating your own.

168
00:07:56,802 --> 00:07:59,010
You can create your own sort
of fragment-like library

169
00:07:59,010 --> 00:08:01,170
implementations if
you feel so inclined.

170
00:08:01,170 --> 00:08:03,330
But you can also create
composite life cycles.

171
00:08:03,330 --> 00:08:06,780
Life cycles that span across
other smaller lifecycle

172
00:08:06,780 --> 00:08:08,010
definitions.

173
00:08:08,010 --> 00:08:10,710
So you can answer questions
like, is my app visible?

174
00:08:10,710 --> 00:08:12,750
So this is a really
common composite lifecycle

175
00:08:12,750 --> 00:08:15,000
that many of you may
be interested in.

176
00:08:15,000 --> 00:08:17,160
It lets you do things
like session management

177
00:08:17,160 --> 00:08:19,530
to track a particular
session across perhaps

178
00:08:19,530 --> 00:08:23,100
some sort of a flow
or a series of logged

179
00:08:23,100 --> 00:08:24,870
in versus logged out events.

180
00:08:24,870 --> 00:08:29,020
And it may help you
with analytics as well.

181
00:08:29,020 --> 00:08:32,280
So we have the process LifeCycle
owner as kind of a component

182
00:08:32,280 --> 00:08:35,350
that I think a lot of you will
be interested in for this.

183
00:08:35,350 --> 00:08:39,058
It's the composite lifecycle of
all the activities in your app.

184
00:08:39,058 --> 00:08:41,009
So there's no configuration
changes to handle,

185
00:08:41,010 --> 00:08:44,440
because we're not going to be
dealing with those from these.

186
00:08:44,440 --> 00:08:46,350
The process LifeCycle
owner just stays

187
00:08:46,350 --> 00:08:48,000
alive through the whole process.

188
00:08:48,000 --> 00:08:50,041
But that also means that
you don't get state risk

189
00:08:50,041 --> 00:08:52,660
restoration after process death
like we mentioned earlier.

190
00:08:52,660 --> 00:08:54,600
So that means that
you don't have

191
00:08:54,600 --> 00:08:56,905
to handle saving and
restoring that state

192
00:08:56,905 --> 00:08:59,280
but at the same time, you need
to remember to re-register

193
00:08:59,280 --> 00:09:02,199
these process lifecycle-based
observers if that's something

194
00:09:02,199 --> 00:09:03,240
that you're working with.

195
00:09:03,240 --> 00:09:05,750


196
00:09:05,750 --> 00:09:09,110
So many indirect
components provide a lot

197
00:09:09,110 --> 00:09:11,330
of deep plumbing
layers for things

198
00:09:11,330 --> 00:09:13,790
that you can plug
into and work with.

199
00:09:13,790 --> 00:09:15,800
But a lot of times
we've kind of omitted

200
00:09:15,800 --> 00:09:17,720
the idea of higher
level components that

201
00:09:17,720 --> 00:09:20,210
make use of that plumbing
so that you can just plug

202
00:09:20,210 --> 00:09:21,280
play and go.

203
00:09:21,280 --> 00:09:24,300
So do we have anything more
high level than the bare events

204
00:09:24,300 --> 00:09:25,530
and states here?

205
00:09:25,530 --> 00:09:26,800
YIGIT BOYAR: Maybe we do.

206
00:09:26,800 --> 00:09:27,760
I will show you.

207
00:09:27,760 --> 00:09:28,870
ADAM POWELL: Great

208
00:09:28,870 --> 00:09:30,530
YIGIT BOYAR: Thanks, Adam.

209
00:09:30,530 --> 00:09:33,680
So it's so nice
now you can observe

210
00:09:33,680 --> 00:09:37,310
a LifeCycle is well-defined,
is a first class citizen.

211
00:09:37,310 --> 00:09:40,530
But you still need to
deal with these things.

212
00:09:40,530 --> 00:09:44,780
And we told like, there's
some common LifeCycle problems

213
00:09:44,780 --> 00:09:47,100
that we should be able to
solve with this component.

214
00:09:47,100 --> 00:09:48,860
So we'll look at the
problems that people

215
00:09:48,860 --> 00:09:51,740
are having, and
this was probably

216
00:09:51,740 --> 00:09:54,110
the most major problem
we've been seeing,

217
00:09:54,110 --> 00:09:56,320
the untimely UI updates.

218
00:09:56,320 --> 00:09:58,920
It's like your activity
receives a callback,

219
00:09:58,920 --> 00:10:00,530
but the activity's
already stopped.

220
00:10:00,530 --> 00:10:03,050
They tried to start a
new activity and crashes.

221
00:10:03,050 --> 00:10:06,010
Or it tries to add a
fragment and crashes.

222
00:10:06,010 --> 00:10:09,410
If an activity or a
fragment is stopped,

223
00:10:09,410 --> 00:10:12,317
there is no reason to
update that activity.

224
00:10:12,317 --> 00:10:13,400
You don't want to do that.

225
00:10:13,400 --> 00:10:16,190
If the activity happens to
become visible again, then

226
00:10:16,190 --> 00:10:17,480
you want to do it.

227
00:10:17,480 --> 00:10:20,480
So we realized that this
is a very common problem,

228
00:10:20,480 --> 00:10:23,990
and we wanted to solve this with
a higher level component which

229
00:10:23,990 --> 00:10:26,060
we call LiveData.

230
00:10:26,060 --> 00:10:29,780
When we look at the
LiveData in detail,

231
00:10:29,780 --> 00:10:32,840
it's actually an
observable data holder.

232
00:10:32,840 --> 00:10:35,180
It just holds on
to some information

233
00:10:35,180 --> 00:10:36,490
that you can observe.

234
00:10:36,490 --> 00:10:38,270
Now the difference
between LiveData

235
00:10:38,270 --> 00:10:41,225
and your other observables
in data mining or RxJava

236
00:10:41,225 --> 00:10:45,350
or whatever, is that
LiveData is LifeCycle aware.

237
00:10:45,350 --> 00:10:48,020
It knows about
Android life cycles,

238
00:10:48,020 --> 00:10:50,030
and when you want to
observe a LiveData,

239
00:10:50,030 --> 00:10:52,580
you can pass in this
LifeCycle so that it

240
00:10:52,580 --> 00:10:54,480
can manage your subscription.

241
00:10:54,480 --> 00:10:57,210
The nice thing about LiveData
that is that you observe,

242
00:10:57,210 --> 00:10:59,340
and that's all you do.

243
00:10:59,340 --> 00:11:00,860
So if we look at
the usage example,

244
00:11:00,860 --> 00:11:02,210
let's say we have an activity.

245
00:11:02,210 --> 00:11:04,110
We receive a LiveData
from somewhere.

246
00:11:04,110 --> 00:11:08,040
It doesn't really matter, and
now we call observe on it.

247
00:11:08,040 --> 00:11:10,160
And when we are
calling observe, we

248
00:11:10,160 --> 00:11:13,600
are passing this, which
is the LiveData owner.

249
00:11:13,600 --> 00:11:14,780
That's all you need to say.

250
00:11:14,780 --> 00:11:18,770
I want to observe this
LiveData within this LifeCycle.

251
00:11:18,770 --> 00:11:21,830
Which also means if
this LifeCycle is gone,

252
00:11:21,830 --> 00:11:23,150
I don't want to observe it.

253
00:11:23,150 --> 00:11:26,550
Or if this LifeCycle is stopped,
I don't want to receive events.

254
00:11:26,550 --> 00:11:30,466


255
00:11:30,466 --> 00:11:32,340
And then once you do
this, that's all you do.

256
00:11:32,340 --> 00:11:34,410
You don't need to
write onStart, onStop.

257
00:11:34,410 --> 00:11:37,870
We want Android to want
to look more like this.

258
00:11:37,870 --> 00:11:40,040
You initialze things as
more like find and forget.

259
00:11:40,040 --> 00:11:43,060
You initialize, and you're done.

260
00:11:43,060 --> 00:11:45,990
So let's look at what happens
when our activity starts

261
00:11:45,990 --> 00:11:47,910
observing that LiveData.

262
00:11:47,910 --> 00:11:52,560
So onCreate, it called observe,
it said LiveData is observable.

263
00:11:52,560 --> 00:11:54,630
And as soon as the
activity starts,

264
00:11:54,630 --> 00:11:56,470
it starts receiving
data changes.

265
00:11:56,470 --> 00:11:59,490
So whenever the
LiveData value changes,

266
00:11:59,490 --> 00:12:01,950
we displace that event
back to your observer

267
00:12:01,950 --> 00:12:03,530
inside the activity.

268
00:12:03,530 --> 00:12:05,450
It can also be a fragment.

269
00:12:05,450 --> 00:12:07,260
Let's say a user
decides to rotate

270
00:12:07,260 --> 00:12:09,090
the activity at this moment.

271
00:12:09,090 --> 00:12:11,540
So you know that the
activity will be stopped.

272
00:12:11,540 --> 00:12:13,320
And what happens
at the same time,

273
00:12:13,320 --> 00:12:16,110
the LiveData happens
to be updated.

274
00:12:16,110 --> 00:12:18,990
If that happens, we are not
going to tell the activity

275
00:12:18,990 --> 00:12:22,590
about this change because there
cannot be any reason for you

276
00:12:22,590 --> 00:12:27,210
to update the UI, because
it already stopped.

277
00:12:27,210 --> 00:12:29,640
Similarly, if the
activity is destroyed,

278
00:12:29,640 --> 00:12:31,980
we will automatically
remove that subscription

279
00:12:31,980 --> 00:12:34,320
because that activity is gone.

280
00:12:34,320 --> 00:12:36,990
There is no reason to
keep a reference back

281
00:12:36,990 --> 00:12:39,240
to that activity.

282
00:12:39,240 --> 00:12:41,010
Now we said the
activity was rotating,

283
00:12:41,010 --> 00:12:42,630
so you know that
Android is going

284
00:12:42,630 --> 00:12:44,880
to recreate that activity.

285
00:12:44,880 --> 00:12:48,270
And then we are observing
the same LiveData back.

286
00:12:48,270 --> 00:12:49,985
As soon as that
activity starts, it's

287
00:12:49,985 --> 00:12:53,190
going to receive
last available data.

288
00:12:53,190 --> 00:12:57,720
So your UI is going to have the
data before it gets a chance

289
00:12:57,720 --> 00:12:59,790
to draw.

290
00:12:59,790 --> 00:13:01,920
So similarly, I
say the user hits

291
00:13:01,920 --> 00:13:05,330
the Home button, which means
the activity will be stopped.

292
00:13:05,330 --> 00:13:08,700
Again, if the LiveData changes
while the activity is stopped,

293
00:13:08,700 --> 00:13:10,840
it's not going to
receive any events.

294
00:13:10,840 --> 00:13:14,010
Even if the data changes,
we are not going to tell it.

295
00:13:14,010 --> 00:13:17,280
But as soon as if the user
comes back to the application,

296
00:13:17,280 --> 00:13:19,510
we will give it the
last available data.

297
00:13:19,510 --> 00:13:22,990
So this is why we call LiveData
is not just a stream of events.

298
00:13:22,990 --> 00:13:26,910
It holds onto the data so
that if any observer comes,

299
00:13:26,910 --> 00:13:30,430
it receives the last
available value.

300
00:13:30,430 --> 00:13:33,620
And then eventually, the user
backs out of that activity,

301
00:13:33,620 --> 00:13:37,830
and then we remove
that subscription.

302
00:13:37,830 --> 00:13:40,730
You can also extend
the LiveData class.

303
00:13:40,730 --> 00:13:45,950
Because LiveData provides
two really handy callbacks.

304
00:13:45,950 --> 00:13:48,410
The first one is called
onactive which means

305
00:13:48,410 --> 00:13:50,930
you have an active observer.

306
00:13:50,930 --> 00:13:52,580
Another one is
called oninactive,

307
00:13:52,580 --> 00:13:54,370
which means you don't
have any observers,

308
00:13:54,370 --> 00:13:56,450
so don't bother
changing your value

309
00:13:56,450 --> 00:14:00,020
if it is something
that you care about.

310
00:14:00,020 --> 00:14:03,800
You probably ask now what
is an active observer?

311
00:14:03,800 --> 00:14:06,220
An active observer
is an observer

312
00:14:06,220 --> 00:14:09,680
whose attached LifeCycle
is started or resumed.

313
00:14:09,680 --> 00:14:12,890
So it's like a fragment that's
currently visible to the user.

314
00:14:12,890 --> 00:14:15,380
If the fragment is
on the back stack,

315
00:14:15,380 --> 00:14:16,660
the user is not seeing it.

316
00:14:16,660 --> 00:14:18,260
It stopped, so it's not active.

317
00:14:18,260 --> 00:14:22,430
There's no reason to do
any work for that fragment.

318
00:14:22,430 --> 00:14:24,850
Let's see how we can take
advantage of these named

319
00:14:24,850 --> 00:14:25,770
callbacks.

320
00:14:25,770 --> 00:14:28,270
We are going to create
a new location LiveData

321
00:14:28,270 --> 00:14:31,190
class, which presents
the location of something

322
00:14:31,190 --> 00:14:32,580
on the device.

323
00:14:32,580 --> 00:14:37,920
So we say this data holds
an instance of a location.

324
00:14:37,920 --> 00:14:40,460
In cross-sector, we just
get the location manager

325
00:14:40,460 --> 00:14:41,850
from the system service.

326
00:14:41,850 --> 00:14:43,670
There's nothing fancy here.

327
00:14:43,670 --> 00:14:47,210
We have a listener whenever
the system server sends us

328
00:14:47,210 --> 00:14:50,830
any location, we just
call setValue on us.

329
00:14:50,830 --> 00:14:51,530
This all you do.

330
00:14:51,530 --> 00:14:53,460
There is no LifeCycle
handling here.

331
00:14:53,460 --> 00:14:56,120
You just call setValue,
and LiveData takes

332
00:14:56,120 --> 00:14:57,710
care of handling the LifeCycle.

333
00:14:57,710 --> 00:15:00,080
And you may have any
number of observers.

334
00:15:00,080 --> 00:15:02,450
It doesn't really matter.

335
00:15:02,450 --> 00:15:04,850
So we want to override onactive.

336
00:15:04,850 --> 00:15:07,340
The very first active
observer comes.

337
00:15:07,340 --> 00:15:10,280
We want to start listening
to the system service.

338
00:15:10,280 --> 00:15:14,300
Similarly, when the last
active observer goes away,

339
00:15:14,300 --> 00:15:19,140
we want to stop observing
the system service.

340
00:15:19,140 --> 00:15:21,800
Now if you look at that
location LiveData class

341
00:15:21,800 --> 00:15:24,020
we just created in the
previous example, let's look

342
00:15:24,020 --> 00:15:26,210
at the properties of that class.

343
00:15:26,210 --> 00:15:28,100
First of all, it
is LifeCycle area.

344
00:15:28,100 --> 00:15:31,280
It knows when to start
itself, when to stop itself.

345
00:15:31,280 --> 00:15:34,340
You just don't need
to babysit it anymore.

346
00:15:34,340 --> 00:15:36,110
It is self-sufficient.

347
00:15:36,110 --> 00:15:37,140
You start it.

348
00:15:37,140 --> 00:15:39,480
You forget about it.

349
00:15:39,480 --> 00:15:40,470
It can be a singleton.

350
00:15:40,470 --> 00:15:42,620
Like all of the subscriptions
are automatically

351
00:15:42,620 --> 00:15:43,850
managed for you.

352
00:15:43,850 --> 00:15:47,090
So if the data is logically
singleton your codebase,

353
00:15:47,090 --> 00:15:50,030
you can make the LiveData
instance singleton.

354
00:15:50,030 --> 00:15:51,710
So there's this
thing where normally

355
00:15:51,710 --> 00:15:54,800
if you keep referencing
an activity or a fragment

356
00:15:54,800 --> 00:15:57,720
from a certain context,
that will be a big no no.

357
00:15:57,720 --> 00:16:00,350
But if you are using
LiveData it is yes yes,

358
00:16:00,350 --> 00:16:05,340
because we manage the
substitution for you.

359
00:16:05,340 --> 00:16:08,550
So you also don't need to
subclass LiveData all the time.

360
00:16:08,550 --> 00:16:10,910
So if you just need
an instance of it

361
00:16:10,910 --> 00:16:12,790
but you already
have the value, you

362
00:16:12,790 --> 00:16:14,990
could use this mutable
LiveData class,

363
00:16:14,990 --> 00:16:18,770
which comes inside the library
that has a public setter.

364
00:16:18,770 --> 00:16:21,170
But usually when you
are using this class,

365
00:16:21,170 --> 00:16:24,530
internally you will have
it but the API you expose

366
00:16:24,530 --> 00:16:26,360
will just return a
LiveData, because you

367
00:16:26,360 --> 00:16:28,370
don't want to expose
the fact that anyone

368
00:16:28,370 --> 00:16:31,470
can set the value on it.

369
00:16:31,470 --> 00:16:34,920
Now when we were designing
these LifeCycle components,

370
00:16:34,920 --> 00:16:38,730
the LiveData, see we
spent a lot of time

371
00:16:38,730 --> 00:16:41,380
to get rid of one exception.

372
00:16:41,380 --> 00:16:43,350
This fragment exception that I--

373
00:16:43,350 --> 00:16:50,520
[APPLAUSE]

374
00:16:50,520 --> 00:16:54,350
We really wanted to say, please,
no more fragment transaction

375
00:16:54,350 --> 00:16:55,460
exceptions.

376
00:16:55,460 --> 00:16:58,570
So LiveData guarantees that
if you received anywhere,

377
00:16:58,570 --> 00:17:00,910
you could run a
fragment transaction.

378
00:17:00,910 --> 00:17:05,310
And to see how we are making
it part of the history,

379
00:17:05,310 --> 00:17:10,118
I want to invite Adam
back to explain it to us.

380
00:17:10,118 --> 00:17:11,539
ADAM POWELL: All
right, so anyone

381
00:17:11,540 --> 00:17:13,205
who has received one
of these exceptions

382
00:17:13,205 --> 00:17:15,289
realizes that it
doesn't just come

383
00:17:15,290 --> 00:17:18,710
from trying to do something
when you just completely stopped

384
00:17:18,710 --> 00:17:20,348
and you absolutely know it.

385
00:17:20,348 --> 00:17:21,889
These exceptions
tend to come in when

386
00:17:21,890 --> 00:17:26,010
you get into very intricate,
nested life cycles.

387
00:17:26,010 --> 00:17:28,910
So we wanted to make sure to be
very thoughtful about defining

388
00:17:28,910 --> 00:17:34,190
how the LifeCycle observer
callbacks are invoked and when.

389
00:17:34,190 --> 00:17:37,400
So in a case like
this, what happens?

390
00:17:37,400 --> 00:17:42,120
You have defined handler
for the stop event.

391
00:17:42,120 --> 00:17:44,872
So in the container
your activity onStop,

392
00:17:44,872 --> 00:17:47,330
you want to make sure that you
don't get an onChanged event

393
00:17:47,330 --> 00:17:48,770
after the onStop has happened.

394
00:17:48,770 --> 00:17:52,660


395
00:17:52,660 --> 00:17:54,570
But in order for
that to happen, what

396
00:17:54,570 --> 00:17:56,490
needs to be true
about when we actually

397
00:17:56,490 --> 00:18:00,030
invoke all of the
onStop listeners

398
00:18:00,030 --> 00:18:02,610
that are attached
to these observers.

399
00:18:02,610 --> 00:18:05,770
So we have to define a
really strict order for this.

400
00:18:05,770 --> 00:18:09,420
So as we go through create
and start and onResume,

401
00:18:09,420 --> 00:18:11,940
we know that we need
to invoke the LifeCycle

402
00:18:11,940 --> 00:18:15,480
observers after the
container event happens.

403
00:18:15,480 --> 00:18:18,090
So you know in your
observer that everything

404
00:18:18,090 --> 00:18:20,461
about your LifeCycle
owner has been configured.

405
00:18:20,461 --> 00:18:21,960
If you check any
state about it, you

406
00:18:21,960 --> 00:18:25,397
know that you're already
completely in that state.

407
00:18:25,397 --> 00:18:27,480
But that means something
really special for coming

408
00:18:27,480 --> 00:18:29,470
back down the other direction.

409
00:18:29,470 --> 00:18:33,540
It means that when the activity
starts to become paused,

410
00:18:33,540 --> 00:18:34,995
you want your
LifeCycle observers

411
00:18:34,995 --> 00:18:36,870
to be able to shut down
anything that they're

412
00:18:36,870 --> 00:18:39,060
doing before the activity
does all of the work

413
00:18:39,060 --> 00:18:41,400
to actually become paused.

414
00:18:41,400 --> 00:18:42,810
Similar for stop.

415
00:18:42,810 --> 00:18:44,850
And this is where
this becomes really

416
00:18:44,850 --> 00:18:47,220
important for the fragment
transaction exception.

417
00:18:47,220 --> 00:18:49,260
You want to make
sure that you're

418
00:18:49,260 --> 00:18:52,440
recording, that you're fully
stopped before the fragment

419
00:18:52,440 --> 00:18:54,600
system goes through
and flags everything

420
00:18:54,600 --> 00:18:58,180
as being completely locked out.

421
00:18:58,180 --> 00:19:01,410
So what that means is that the
stop event of your LifeCycle

422
00:19:01,410 --> 00:19:04,770
observer will always be invoked
before the activity onStop

423
00:19:04,770 --> 00:19:10,710
or before the full stop event
for your container happens.

424
00:19:10,710 --> 00:19:13,260
So this seems really similar
to some other libraries

425
00:19:13,260 --> 00:19:15,480
that some people may
have seen in the past.

426
00:19:15,480 --> 00:19:16,600
Can you talk about that?

427
00:19:16,600 --> 00:19:22,530
SERGEI VASILINETC: Yes, when we
create new observable pattern,

428
00:19:22,530 --> 00:19:26,220
nowadays this question
is unavoidable.

429
00:19:26,220 --> 00:19:29,220
Is it another RxJava?

430
00:19:29,220 --> 00:19:32,490
And the answer to
this question is, yes,

431
00:19:32,490 --> 00:19:34,740
because we want to promote
a reactive programming

432
00:19:34,740 --> 00:19:37,980
model, especially when it
comes to the relationship

433
00:19:37,980 --> 00:19:40,710
between your UI and the
state [INAUDIBLE] UI.

434
00:19:40,710 --> 00:19:45,490
We want you to react on
the changes of the state.

435
00:19:45,490 --> 00:19:48,300
So it means that it's a
reactive programming model.

436
00:19:48,300 --> 00:19:51,000
But on the other hand, no.

437
00:19:51,000 --> 00:19:54,840
Because it's the LifeCycle
aware out of box,

438
00:19:54,840 --> 00:19:57,930
as Yigit mentioned,
and it's much easier.

439
00:19:57,930 --> 00:20:02,940
As many of you may know,
the learning curve of RxJava

440
00:20:02,940 --> 00:20:04,560
is super steep.

441
00:20:04,560 --> 00:20:08,850
And if you have an
Android learner curve,

442
00:20:08,850 --> 00:20:13,350
and after that we add RxJava
learning curve on top of it,

443
00:20:13,350 --> 00:20:16,050
it becomes very
hard to new people

444
00:20:16,050 --> 00:20:19,420
to start to develop
on our platform.

445
00:20:19,420 --> 00:20:25,890
So we can't just say to them,
oh let's go, just learn this,

446
00:20:25,890 --> 00:20:27,330
that's it. .

447
00:20:27,330 --> 00:20:32,310
No, but if you already
learned RxJava,

448
00:20:32,310 --> 00:20:37,020
we don't expect you to migrate
from it to our solution.

449
00:20:37,020 --> 00:20:41,280
Because you already
passed the learning curve,

450
00:20:41,280 --> 00:20:45,960
you and your coworkers are
comfortable with it, fine.

451
00:20:45,960 --> 00:20:48,190
We are totally fine with this.

452
00:20:48,190 --> 00:20:51,330
But one thing we ask
you to do is to be sure

453
00:20:51,330 --> 00:20:53,920
that you manage LifeCycle.

454
00:20:53,920 --> 00:20:58,210
RxJava has common
approaches to solve this.

455
00:20:58,210 --> 00:21:02,430
Be sure to use it and
everything will be fine.

456
00:21:02,430 --> 00:21:09,885
But when you start a new app,
I think this model is the best.

457
00:21:09,885 --> 00:21:15,010
The best is to start the project
with LiveData, because it's

458
00:21:15,010 --> 00:21:17,310
simpler, it's faster,
it's lightweight,

459
00:21:17,310 --> 00:21:20,270
it's well integrated
with a framework.

460
00:21:20,270 --> 00:21:24,970
And if you feel like you love
reacting programming a lot,

461
00:21:24,970 --> 00:21:28,480
you want to bring it
not only to relation

462
00:21:28,480 --> 00:21:31,930
between UI and the state.

463
00:21:31,930 --> 00:21:33,430
You want to bring
it to the business

464
00:21:33,430 --> 00:21:36,340
part of your application.

465
00:21:36,340 --> 00:21:41,070
Then you may consider
the addition of RxJava,

466
00:21:41,070 --> 00:21:44,230
because it gives you more power.

467
00:21:44,230 --> 00:21:47,140
And we will actually
help you to do that.

468
00:21:47,140 --> 00:21:51,790
We have this extension
to our library, which

469
00:21:51,790 --> 00:21:55,780
gives a possibility to create
LiveData from Publisher

470
00:21:55,780 --> 00:21:58,930
and create Publisher
from LiveData.

471
00:21:58,930 --> 00:22:03,970
So this integration
should be quite smooth.

472
00:22:03,970 --> 00:22:07,330
But I want to highlight a
key difference between RxJava

473
00:22:07,330 --> 00:22:08,080
and LiveData.

474
00:22:08,080 --> 00:22:11,980
So as Yigit already
said, LiveData

475
00:22:11,980 --> 00:22:13,870
is a holder and not a stream.

476
00:22:13,870 --> 00:22:17,320
So we have a reference
to the last value,

477
00:22:17,320 --> 00:22:20,290
and observers immediately
receive the last value when

478
00:22:20,290 --> 00:22:24,820
they start to observe LiveData.

479
00:22:24,820 --> 00:22:27,550
And now the big difference
is a threading model.

480
00:22:27,550 --> 00:22:31,840
As you know, RxJava has a very
sophisticated threading model.

481
00:22:31,840 --> 00:22:35,390
It's extremely powerful,
but in most cases,

482
00:22:35,390 --> 00:22:37,610
you probably don't need it.

483
00:22:37,610 --> 00:22:40,360
And we have everything
on the main thread.

484
00:22:40,360 --> 00:22:42,190
And the reason for
this is we want

485
00:22:42,190 --> 00:22:47,150
to give you all these guarantees
about when we will notify you

486
00:22:47,150 --> 00:22:50,740
about state changes.

487
00:22:50,740 --> 00:22:56,200
And we can't do this
on a background thread.

488
00:22:56,200 --> 00:22:58,330
We have just the one exception.

489
00:22:58,330 --> 00:23:00,850
We have a post
value method which

490
00:23:00,850 --> 00:23:03,720
just is a method
which trampoline value

491
00:23:03,720 --> 00:23:07,725
from a background thread to the
main thread and sets it there.

492
00:23:07,725 --> 00:23:08,770
It's super simple.

493
00:23:08,770 --> 00:23:11,400
So quick summary of what
we have at this point.

494
00:23:11,400 --> 00:23:13,870
LiveData events,
observable pattern

495
00:23:13,870 --> 00:23:16,460
which respects these events.

496
00:23:16,460 --> 00:23:20,090
But there is one big thing
which is not covered yet.

497
00:23:20,090 --> 00:23:23,590
And this is how to handle
onConfigurationChanges.

498
00:23:23,590 --> 00:23:28,690
In 2017, almost nine
years after Android

499
00:23:28,690 --> 00:23:32,050
was first time released, we
still discuss this question.

500
00:23:32,050 --> 00:23:34,090
And this is a totally
legit question.

501
00:23:34,090 --> 00:23:38,290
And we hear it constantly
from new Android developers.

502
00:23:38,290 --> 00:23:40,730
Many of you probably know
whats the deal with it.

503
00:23:40,730 --> 00:23:44,770
But let's take a look at
this oversimplified example,

504
00:23:44,770 --> 00:23:47,830
but it's still very vivid.

505
00:23:47,830 --> 00:23:50,050
So he wants to show
this information

506
00:23:50,050 --> 00:23:52,060
about user and your activity.

507
00:23:52,060 --> 00:23:54,830
And you want to make
some web service request.

508
00:23:54,830 --> 00:24:00,340
We will use LiveData to get
this result. It's super simple.

509
00:24:00,340 --> 00:24:02,800
When the request is just
started, it's empty.

510
00:24:02,800 --> 00:24:06,620
When the request
response is received,

511
00:24:06,620 --> 00:24:11,740
we put it to
LiveData as a value.

512
00:24:11,740 --> 00:24:14,070
And later we'll update our UI.

513
00:24:14,070 --> 00:24:19,917
We will notify the activity, and
it will do everything it needs.

514
00:24:19,917 --> 00:24:22,250
So what happens if the activity
is going to [INAUDIBLE].

515
00:24:22,250 --> 00:24:25,750
We're going to
make a call twice,

516
00:24:25,750 --> 00:24:28,560
and I hope that you don't
call web service right

517
00:24:28,560 --> 00:24:29,740
into your activity.

518
00:24:29,740 --> 00:24:33,670
But you probably have
some abstractions

519
00:24:33,670 --> 00:24:36,010
that does something
like that, which

520
00:24:36,010 --> 00:24:41,040
goes to a network, which goes
to caching and persistence

521
00:24:41,040 --> 00:24:43,030
storages.

522
00:24:43,030 --> 00:24:47,170
And all the separations
are synchronized by nature.

523
00:24:47,170 --> 00:24:51,070
So communication of these
components are synchronized.

524
00:24:51,070 --> 00:24:55,510
And you probably don't want to
make these calls twice anyway.

525
00:24:55,510 --> 00:24:58,060
So what you want
to do is to cache.

526
00:24:58,060 --> 00:25:01,470
This is our data,
like in our example.

527
00:25:01,470 --> 00:25:04,480
And what are the ways
today to do that?

528
00:25:04,480 --> 00:25:06,960
Well, one of a
proposed way to do it

529
00:25:06,960 --> 00:25:10,570
is a Fragment.setRetainInstance,
and Yigit

530
00:25:10,570 --> 00:25:12,340
can rant about this for hours.

531
00:25:12,340 --> 00:25:14,770
Unfortunately, we don't
have time for this today.

532
00:25:14,770 --> 00:25:17,600
But I just say that
the only effect

533
00:25:17,600 --> 00:25:19,900
that you have to run
fragment transaction

534
00:25:19,900 --> 00:25:22,400
is terrifying for
a lot of people.

535
00:25:22,400 --> 00:25:25,780
People go nuts and
another possible way

536
00:25:25,780 --> 00:25:29,960
to solve this is loaders, but
we don't fit here well as well.

537
00:25:29,960 --> 00:25:33,010
So we decided to tackle
this problem once again

538
00:25:33,010 --> 00:25:35,230
and create ViewModel.

539
00:25:35,230 --> 00:25:36,030
So what is this?

540
00:25:36,030 --> 00:25:39,070
ViewModel is an object
which is associated

541
00:25:39,070 --> 00:25:41,440
with a fragment or an
activity, but is retained

542
00:25:41,440 --> 00:25:43,750
during configuration changes.

543
00:25:43,750 --> 00:25:48,190
So its scope is a kind of a
logical scope of your activity.

544
00:25:48,190 --> 00:25:51,300
So what does this mean?

545
00:25:51,300 --> 00:25:51,900
Let's see.

546
00:25:51,900 --> 00:25:54,220
If we have access time and
the current moment, and we

547
00:25:54,220 --> 00:25:55,540
can predict the future.

548
00:25:55,540 --> 00:25:57,670
And we know that activity
is going to be created,

549
00:25:57,670 --> 00:25:59,390
and this means that
all construction

550
00:25:59,390 --> 00:26:01,690
events are going to happen.

551
00:26:01,690 --> 00:26:05,440
During onCreate we will request
ViewModel for the first time.

552
00:26:05,440 --> 00:26:07,780
We will create it, and
after that this activity

553
00:26:07,780 --> 00:26:10,850
just uses this ViewModel.

554
00:26:10,850 --> 00:26:12,220
Very simple.

555
00:26:12,220 --> 00:26:16,060
Now we predict that the
activity is going to be rotated.

556
00:26:16,060 --> 00:26:20,700
Let's see what's going to
happen with our ViewModel.

557
00:26:20,700 --> 00:26:27,400
We will receive events,
onPause, onStop, and onDestroy.

558
00:26:27,400 --> 00:26:30,880
But when all the
segments are cured

559
00:26:30,880 --> 00:26:34,090
and your activity is
destroyed, it's thrown away

560
00:26:34,090 --> 00:26:38,210
and is garbage collected,
ViewModel survived it.

561
00:26:38,210 --> 00:26:42,070
And the new activity, which was
created in place the old one

562
00:26:42,070 --> 00:26:44,510
uses the same, old object.

563
00:26:44,510 --> 00:26:48,520
So you can easily cache
there LiveData as we want to

564
00:26:48,520 --> 00:26:50,690
or something else.

565
00:26:50,690 --> 00:26:52,720
The last case, what
is going to happen

566
00:26:52,720 --> 00:26:55,600
if you have finished goal?

567
00:26:55,600 --> 00:26:58,280
Once again, we will receive
these destruction events,

568
00:26:58,280 --> 00:27:01,570
but this time,
ViewModel is available

569
00:27:01,570 --> 00:27:03,130
until onDestroy method.

570
00:27:03,130 --> 00:27:08,340
During onDestroy method, we
will call onClear on this.

571
00:27:08,340 --> 00:27:11,860
Which notifies you if you have
any currently running actions

572
00:27:11,860 --> 00:27:15,610
or any resources
its time to close.

573
00:27:15,610 --> 00:27:18,900
And after that, it's
going to be destroyed

574
00:27:18,900 --> 00:27:20,150
and garbage collected as well.

575
00:27:20,150 --> 00:27:24,310
So at the point when your
activity is destroyed,

576
00:27:24,310 --> 00:27:27,340
it's not going to be
recreated it again.

577
00:27:27,340 --> 00:27:30,980
Your ViewModel is gone as well.

578
00:27:30,980 --> 00:27:37,970
So let's quickly make
our sample in ViewModel.

579
00:27:37,970 --> 00:27:40,900
So it starts with
instantiating-- with creation

580
00:27:40,900 --> 00:27:43,270
of ViewModel class.

581
00:27:43,270 --> 00:27:47,860
We want to cache for user data
to create a fill for that.

582
00:27:47,860 --> 00:27:50,680
We agree our activity needs
to access this LiveData,

583
00:27:50,680 --> 00:27:52,450
so we create a getter for this.

584
00:27:52,450 --> 00:27:55,960
And finally, getter is
extremely straightforward.

585
00:27:55,960 --> 00:27:59,530
If we already requested the
data, we just return it.

586
00:27:59,530 --> 00:28:04,780
If the data is now, we'll
request it from a web service

587
00:28:04,780 --> 00:28:06,580
and return it.

588
00:28:06,580 --> 00:28:07,422
Fine.

589
00:28:07,422 --> 00:28:08,880
We had [INAUDIBLE]
on our activity.

590
00:28:08,880 --> 00:28:12,580
Now we need to get this
LiveData from ViewModel.

591
00:28:12,580 --> 00:28:18,370
To get it, we need to create
to get ViewModel somehow.

592
00:28:18,370 --> 00:28:19,450
So this is how we do it.

593
00:28:19,450 --> 00:28:21,970
Let's take a precise look at it.

594
00:28:21,970 --> 00:28:25,000
First of all, we need to get
ViewModel provider object.

595
00:28:25,000 --> 00:28:27,250
This is an object
which is associated

596
00:28:27,250 --> 00:28:28,570
with a fragment or an activity.

597
00:28:28,570 --> 00:28:34,270
It knows how to get already
existing ViewModel from it

598
00:28:34,270 --> 00:28:36,740
or how to create a new one.

599
00:28:36,740 --> 00:28:39,250
If there is no
existing ViewModel.

600
00:28:39,250 --> 00:28:44,650
After that, we request
our myActivity ViewModel,

601
00:28:44,650 --> 00:28:48,617
and later everything
is quite simple.

602
00:28:48,617 --> 00:28:49,450
We get the userData.

603
00:28:49,450 --> 00:28:54,730
We observe it to update the UI.

604
00:28:54,730 --> 00:28:59,860
So what are the rules
of usage of ViewModel?

605
00:28:59,860 --> 00:29:04,660
So ViewModel manages
the data for the UI.

606
00:29:04,660 --> 00:29:08,290
It means that it
speaks with business

607
00:29:08,290 --> 00:29:11,510
parts of your application
to retrieve the data.

608
00:29:11,510 --> 00:29:15,470
So it may be a repository
pattern or any other pattern

609
00:29:15,470 --> 00:29:17,890
that they use.

610
00:29:17,890 --> 00:29:22,450
It also, it's for its
user modifications

611
00:29:22,450 --> 00:29:24,140
back to these components.

612
00:29:24,140 --> 00:29:26,720
And now a good
case for ViewModel

613
00:29:26,720 --> 00:29:30,730
is acting as a communication
layer between fragments

614
00:29:30,730 --> 00:29:32,530
in one activity.

615
00:29:32,530 --> 00:29:36,490
And Yigit will speak
about this later.

616
00:29:36,490 --> 00:29:40,840
But prior to this,
things that you must not

617
00:29:40,840 --> 00:29:42,560
do in your ViewModel.

618
00:29:42,560 --> 00:29:46,580
So first of all,
you must not access

619
00:29:46,580 --> 00:29:51,870
views and any other
UI- related entities.

620
00:29:51,870 --> 00:29:54,670
The reason for
that, they are going

621
00:29:54,670 --> 00:29:57,010
to be created during
configuration change.

622
00:29:57,010 --> 00:30:02,400
If you try to use them, you will
ever use stale data from there,

623
00:30:02,400 --> 00:30:05,250
ever to leak them.

624
00:30:05,250 --> 00:30:09,230
That's going to finish bad.

625
00:30:09,230 --> 00:30:12,280
And it's fragmented
or activity's job

626
00:30:12,280 --> 00:30:17,110
to bind the data which you
will get from a ViewModel

627
00:30:17,110 --> 00:30:21,260
with actual UI,
text use, buttons.

628
00:30:21,260 --> 00:30:23,190
I don't know what else.

629
00:30:23,190 --> 00:30:26,590
And one more thing,
there are sources

630
00:30:26,590 --> 00:30:31,120
which sound more harmless
like strings or drawable,

631
00:30:31,120 --> 00:30:33,790
and you may think,
I may cash it here.

632
00:30:33,790 --> 00:30:38,020
No, they depend on current
configuration state of state

633
00:30:38,020 --> 00:30:38,800
as well.

634
00:30:38,800 --> 00:30:43,360
So yes, right now you may
have just one resource

635
00:30:43,360 --> 00:30:46,540
for every configuration,
but later, you

636
00:30:46,540 --> 00:30:49,870
will add in the same resource
for a different configuration.

637
00:30:49,870 --> 00:30:54,010
You will easily forget
to update your ViewModel.

638
00:30:54,010 --> 00:30:58,540
And you may not notice
this, but your users

639
00:30:58,540 --> 00:31:00,250
will see the invalid UI.

640
00:31:00,250 --> 00:31:02,230
And this is just ugly.

641
00:31:02,230 --> 00:31:06,970
And now Yigit will speak about
Inter Fragment communications.

642
00:31:06,970 --> 00:31:10,510


643
00:31:10,510 --> 00:31:12,270
YIGIT BOYAR: So I
want to talk about one

644
00:31:12,270 --> 00:31:16,050
of my favorite features
about ViewModel,

645
00:31:16,050 --> 00:31:19,020
which is communicating
between multiple fragments

646
00:31:19,020 --> 00:31:21,980
of the same activity.

647
00:31:21,980 --> 00:31:25,200
It's good that UI like this,
like the Gmail on the tablet

648
00:31:25,200 --> 00:31:29,500
where on the left side you pick
an email and on the right side,

649
00:31:29,500 --> 00:31:31,860
it shows the contents
of the email.

650
00:31:31,860 --> 00:31:34,560
Now usually you will
implement this as a fragment

651
00:31:34,560 --> 00:31:37,940
on the left which picks
something from the list,

652
00:31:37,940 --> 00:31:39,780
and another fragment
on the right, which

653
00:31:39,780 --> 00:31:42,960
shows how to show the
contents of an email

654
00:31:42,960 --> 00:31:45,330
so that if you're on the
phone you can reuse the same

655
00:31:45,330 --> 00:31:48,150
fragments but separate
from each other.

656
00:31:48,150 --> 00:31:52,170
Now if you ever tried to write
a UI like this, if you ever

657
00:31:52,170 --> 00:31:55,105
tried to make these two
fragments talk to each other,

658
00:31:55,105 --> 00:31:56,220
it's a pain in the neck.

659
00:31:56,220 --> 00:31:57,240
It's very, very hard.

660
00:31:57,240 --> 00:31:59,510
Like you need to
create an interface.

661
00:31:59,510 --> 00:32:01,530
But then what if
one fragment gets

662
00:32:01,530 --> 00:32:03,540
created before the other one.

663
00:32:03,540 --> 00:32:05,940
An activity needs to
talk to each other.

664
00:32:05,940 --> 00:32:07,931
Or like when the
activities are restored,

665
00:32:07,931 --> 00:32:09,430
you don't really
know which fragment

666
00:32:09,430 --> 00:32:11,340
will be restored first.

667
00:32:11,340 --> 00:32:14,880
It is really hard to
manage this state.

668
00:32:14,880 --> 00:32:21,020
But we can actually solve this
very elegantly using ViewModel.

669
00:32:21,020 --> 00:32:23,930
So let's say so these two
families actually want

670
00:32:23,930 --> 00:32:26,390
to talk about a selected email.

671
00:32:26,390 --> 00:32:29,060
This is the information
they want to share.

672
00:32:29,060 --> 00:32:30,950
So let's put it
inside a ViewModel

673
00:32:30,950 --> 00:32:33,920
and we are going to call
this shared ViewModel.

674
00:32:33,920 --> 00:32:36,130
So it has a mutable
LiveData inside it

675
00:32:36,130 --> 00:32:41,430
which you call selected, and it
provides two very simple APIs.

676
00:32:41,430 --> 00:32:45,410
The first one says, set the
select email to this email.

677
00:32:45,410 --> 00:32:49,610
Another one says, get the
selected email as a LiveData.

678
00:32:49,610 --> 00:32:52,510
It's a really simple ViewModel.

679
00:32:52,510 --> 00:32:56,030
But now once we have this,
let's go back to our fragments

680
00:32:56,030 --> 00:32:58,260
and see how we can use this.

681
00:32:58,260 --> 00:33:00,920
So inside the content
fragment, which is the one

682
00:33:00,920 --> 00:33:03,650
that wants to display the
contents of the email.

683
00:33:03,650 --> 00:33:07,550
It wants to know when the
selected email changes.

684
00:33:07,550 --> 00:33:09,930
So we're going to go-- so
we have already seen this.

685
00:33:09,930 --> 00:33:12,470
You can go to ViewModel
providers class

686
00:33:12,470 --> 00:33:15,230
and get the ViewModel
providers of this fragment.

687
00:33:15,230 --> 00:33:19,170
But we actually want ViewModel
not from this fragment,

688
00:33:19,170 --> 00:33:21,330
we want it from our activity.

689
00:33:21,330 --> 00:33:25,480
So all you have to do tell it
to do it from your activity.

690
00:33:25,480 --> 00:33:28,520
Now it's going to return your
ViewModel in the activity

691
00:33:28,520 --> 00:33:33,140
scope, and I will say, get
for the shared ViewModel.

692
00:33:33,140 --> 00:33:35,770
Now, the very first time one
of the fragments called this,

693
00:33:35,770 --> 00:33:37,460
we are going to
create a new one.

694
00:33:37,460 --> 00:33:39,520
When the other
fragment comes alive,

695
00:33:39,520 --> 00:33:42,830
it's going to receive the
same ViewModel instance.

696
00:33:42,830 --> 00:33:44,100
And I will do the same thing.

697
00:33:44,100 --> 00:33:46,650
So this one says, get
the selected email.

698
00:33:46,650 --> 00:33:48,662
Start observing on it.

699
00:33:48,662 --> 00:33:50,540
Really similarly, in
the select fragment

700
00:33:50,540 --> 00:33:54,500
which was the one on the
left by user pics and email,

701
00:33:54,500 --> 00:33:57,410
we get the same ViewModel.

702
00:33:57,410 --> 00:34:00,680
And whenever the user selects
an email from the list,

703
00:34:00,680 --> 00:34:03,080
we just call the
ViewModel- related method

704
00:34:03,080 --> 00:34:05,120
to change the selected email.

705
00:34:05,120 --> 00:34:08,239
Now these two fragments
talking to each other

706
00:34:08,239 --> 00:34:10,710
without actually
talking to each other.

707
00:34:10,710 --> 00:34:13,730
How does this really happen?

708
00:34:13,730 --> 00:34:15,380
So if we go back to our UI.

709
00:34:15,380 --> 00:34:18,679
So we have the selector on the
left, the content on the right.

710
00:34:18,679 --> 00:34:21,320
But if you look at the
details, actually both of these

711
00:34:21,320 --> 00:34:23,060
are talking to a
shared ViewModel.

712
00:34:23,060 --> 00:34:25,040
They never talk to each other.

713
00:34:25,040 --> 00:34:28,580
The video of this solution is
that if you're on the phone,

714
00:34:28,580 --> 00:34:31,280
let's say one fragment
replaces the other one,

715
00:34:31,280 --> 00:34:33,080
there's no room for error.

716
00:34:33,080 --> 00:34:35,270
Like the fragment still
talks to a ViewModel.

717
00:34:35,270 --> 00:34:37,370
ViewModels always that
nothing will crash.

718
00:34:37,370 --> 00:34:39,770
They don't even care
the other one is there.

719
00:34:39,770 --> 00:34:42,810


720
00:34:42,810 --> 00:34:45,349
Okay, so this is a
lot of information,

721
00:34:45,349 --> 00:34:47,670
and there's further
details about how

722
00:34:47,670 --> 00:34:49,170
these life cycles work.

723
00:34:49,170 --> 00:34:51,330
We really spent a
lot of time to make

724
00:34:51,330 --> 00:34:55,260
these handle most common
used cases on Android.

725
00:34:55,260 --> 00:34:58,620
So we come in just
the first trade out.

726
00:34:58,620 --> 00:35:03,150
You could try it
now, in [INAUDIBLE].

727
00:35:03,150 --> 00:35:05,850
Please check out all of the
architecture components.

728
00:35:05,850 --> 00:35:08,640
These are things that actually
work very well together.

729
00:35:08,640 --> 00:35:11,070
We have an architecture
guide which shows you

730
00:35:11,070 --> 00:35:15,330
how to use these things together
to write a good application.

731
00:35:15,330 --> 00:35:16,980
And also check our code labs.

732
00:35:16,980 --> 00:35:20,490
We have code lab sections that
will give you a first glimpse

733
00:35:20,490 --> 00:35:23,841
of how LifeCycles work.

734
00:35:23,841 --> 00:35:24,340
Thank you

735
00:35:24,340 --> 00:35:26,815
[APPLAUSE]

736
00:35:26,815 --> 00:35:29,055
[MUSIC PLAYING]

737
00:35:29,055 --> 00:00:00,000


09 09 2017

Теги заметки: