WEBVTT

1
00:00:00.040 --> 00:00:02.279
<v Speaker 1>Never picked up your phone, open an app you use

2
00:00:02.319 --> 00:00:06.040
<v Speaker 1>all the time, and then just nothing, just a frozen screen,

3
00:00:06.040 --> 00:00:08.240
<v Speaker 1>maybe a little spinner, or you get that absolutely dreaded

4
00:00:08.439 --> 00:00:12.400
<v Speaker 1>application not responding message asking if you want to force quit?

5
00:00:12.519 --> 00:00:14.839
<v Speaker 2>Oh, I know that feeling. It's instantly frustrating, isn't It

6
00:00:14.960 --> 00:00:18.199
<v Speaker 2>basically screams this app is broken at the user. And

7
00:00:18.280 --> 00:00:21.879
<v Speaker 2>almost every single time that feeling, it's because the app's

8
00:00:22.000 --> 00:00:23.760
<v Speaker 2>main thread got completely tied up.

9
00:00:23.879 --> 00:00:26.600
<v Speaker 1>The main thread that's like the nerve center of the

10
00:00:26.640 --> 00:00:29.920
<v Speaker 1>app on Android gap, the bit doing everything you see

11
00:00:29.960 --> 00:00:31.280
<v Speaker 1>and interact with exactly.

12
00:00:31.320 --> 00:00:33.560
<v Speaker 2>It's often called the UI thread, and for good reason,

13
00:00:33.640 --> 00:00:37.200
<v Speaker 2>it draws everything on the screen, handles your taps, your swipes,

14
00:00:37.320 --> 00:00:41.719
<v Speaker 2>runs crucial activity callbacks. Think of it like, well, a

15
00:00:41.880 --> 00:00:44.200
<v Speaker 2>very busy air traffic controller for the UI.

16
00:00:44.200 --> 00:00:47.280
<v Speaker 1>And if that controller gets bogged down trying to I

17
00:00:47.320 --> 00:00:50.159
<v Speaker 1>don't know, calculate pie to a million places instead of

18
00:00:50.280 --> 00:00:51.520
<v Speaker 1>landing planes.

19
00:00:51.200 --> 00:00:54.520
<v Speaker 2>Everything grinds to a halt. The UI freezes solid.

20
00:00:54.840 --> 00:00:57.920
<v Speaker 1>So blocking that main thread, that's the real villain behind

21
00:00:57.960 --> 00:01:03.000
<v Speaker 1>the unresponsiveness, that jerky animations, the jank and yeah, ultimately

22
00:01:03.079 --> 00:01:07.040
<v Speaker 1>that anr dialogue precisely Okay, so our source material for

23
00:01:07.079 --> 00:01:11.719
<v Speaker 1>this deep dive asynchronous Android by Steve Lyles. It goes

24
00:01:11.840 --> 00:01:15.599
<v Speaker 1>right into this problem. It's all about using the power

25
00:01:15.599 --> 00:01:19.200
<v Speaker 1>of modern phones, you know, with their multiple process or

26
00:01:19.239 --> 00:01:20.400
<v Speaker 1>core is just sitting.

27
00:01:20.079 --> 00:01:22.400
<v Speaker 2>There right, leveraging that power to keep.

28
00:01:22.200 --> 00:01:26.040
<v Speaker 1>Apps smooth and responsive by doing work off that critical

29
00:01:26.079 --> 00:01:26.640
<v Speaker 1>main thread.

30
00:01:26.840 --> 00:01:29.319
<v Speaker 2>Yeah, and our mission today is basically to unpack the

31
00:01:29.439 --> 00:01:32.319
<v Speaker 2>key ideas and tools Android gives us for handling this

32
00:01:32.359 --> 00:01:35.760
<v Speaker 2>background work properly. We want to give you, the listener,

33
00:01:35.840 --> 00:01:38.760
<v Speaker 2>a kind of shortcut to understanding how to build apps

34
00:01:38.760 --> 00:01:41.879
<v Speaker 2>that actually feel responsive, drawing straight from the book.

35
00:01:42.000 --> 00:01:45.200
<v Speaker 1>Right, mission accepted, Let's dive in. So why is this

36
00:01:45.239 --> 00:01:49.159
<v Speaker 1>such a big deal on mobile specifically compared to say

37
00:01:49.200 --> 00:01:50.040
<v Speaker 1>a desktop app.

38
00:01:50.159 --> 00:01:52.879
<v Speaker 2>Well, mobile devices, even though they're super powerful now, they

39
00:01:52.920 --> 00:01:55.840
<v Speaker 2>still operate under tighter constraints than a desktop or a server.

40
00:01:55.920 --> 00:01:59.159
<v Speaker 2>You know, limited battery, often less ram efficiency.

41
00:01:58.640 --> 00:02:00.799
<v Speaker 1>Is key, right, And like you said, each Android app

42
00:02:00.799 --> 00:02:03.680
<v Speaker 1>process usually just gets that one main thread and all

43
00:02:03.680 --> 00:02:05.400
<v Speaker 1>the critical UI stuff happens there.

44
00:02:05.640 --> 00:02:08.680
<v Speaker 2>And this is where it gets really painful if you're

45
00:02:08.680 --> 00:02:11.360
<v Speaker 2>not careful, If you try to do anything that takes

46
00:02:11.400 --> 00:02:14.400
<v Speaker 2>a noticeable amount of time reading a big file, doing

47
00:02:14.439 --> 00:02:17.639
<v Speaker 2>heavy math, or the classic one making a network request.

48
00:02:17.680 --> 00:02:19.680
<v Speaker 2>If you do that directly on them a main thread.

49
00:02:19.520 --> 00:02:22.560
<v Speaker 1>That's when the trouble starts. How quickly does it become noticeable?

50
00:02:22.719 --> 00:02:23.960
<v Speaker 1>Like how much time is too much?

51
00:02:24.280 --> 00:02:26.439
<v Speaker 2>Oh, a user will feel a delay of even just

52
00:02:26.479 --> 00:02:30.759
<v Speaker 2>a couple hundred milliseconds. But for smooth UI for animations

53
00:02:30.800 --> 00:02:34.400
<v Speaker 2>and scrolling, you're aiming for sixty frames per second. That

54
00:02:34.439 --> 00:02:38.039
<v Speaker 2>means you have about sixteen point sixty seven milliseconds to

55
00:02:38.159 --> 00:02:39.199
<v Speaker 2>draw each frame.

56
00:02:39.439 --> 00:02:41.520
<v Speaker 1>Wow, it's not much time at all, not at all.

57
00:02:41.560 --> 00:02:43.759
<v Speaker 2>And if your main thread is busy doing something else

58
00:02:43.840 --> 00:02:46.800
<v Speaker 2>for longer than that sixteen milliseconds, you drop a frame.

59
00:02:47.280 --> 00:02:51.560
<v Speaker 2>That's the jank. Your smooth scrolling suddenly becomes a stuttering mess.

60
00:02:51.840 --> 00:02:54.479
<v Speaker 1>And the absolute worst case the ANR.

61
00:02:54.599 --> 00:02:57.719
<v Speaker 2>The ANR, Yeah, block that main thread for five whole seconds,

62
00:02:57.759 --> 00:03:00.759
<v Speaker 2>and Android basically throws its hands up. This app is

63
00:03:00.800 --> 00:03:03.759
<v Speaker 2>stuck and shows that dialogue offering to kill it. The

64
00:03:03.800 --> 00:03:06.639
<v Speaker 2>system takes unresponsiveness very seriously.

65
00:03:06.719 --> 00:03:09.400
<v Speaker 1>Even built in protections at the platform level, didn't they.

66
00:03:09.360 --> 00:03:12.840
<v Speaker 2>They definitely did. You've got developer tools like strict mode,

67
00:03:12.919 --> 00:03:16.400
<v Speaker 2>which can flash the screen red if you do slow

68
00:03:16.520 --> 00:03:20.719
<v Speaker 2>operations on the main thread during development handy and crucially,

69
00:03:21.199 --> 00:03:25.199
<v Speaker 2>starting back in Honeycomb API eleven, they introduced the network

70
00:03:25.199 --> 00:03:27.360
<v Speaker 2>on main thread exception. If you try to make a

71
00:03:27.400 --> 00:03:29.919
<v Speaker 2>network call on the main thread in a modern app,

72
00:03:30.039 --> 00:03:31.759
<v Speaker 2>it just crashes boom.

73
00:03:31.800 --> 00:03:33.960
<v Speaker 1>So they're literally stopping you from making that mistake.

74
00:03:34.000 --> 00:03:36.840
<v Speaker 2>They are actively pushing you away from it, which leads

75
00:03:36.840 --> 00:03:41.039
<v Speaker 2>to the fundamental solution the source hammers home. You have

76
00:03:41.080 --> 00:03:46.080
<v Speaker 2>to offload long running work, heavy computation file io network calls,

77
00:03:46.120 --> 00:03:48.719
<v Speaker 2>get them onto background threads, let the main thread focus

78
00:03:48.759 --> 00:03:49.240
<v Speaker 2>on the UI.

79
00:03:49.680 --> 00:03:54.319
<v Speaker 1>Simple idea, but I guess managing multiple threads isn't always straightforward.

80
00:03:53.719 --> 00:03:55.599
<v Speaker 2>Not at all. That's why you run into the classic

81
00:03:55.639 --> 00:03:59.800
<v Speaker 2>headaches of concurrent programming. You get correctness issues like race.

82
00:03:59.639 --> 00:04:02.159
<v Speaker 1>Condition Race conditions was a simple example of that.

83
00:04:02.400 --> 00:04:05.919
<v Speaker 2>The book uses a great one. Imagine an integer variable

84
00:04:06.120 --> 00:04:09.560
<v Speaker 2>mind starting at zero, Thread A reads it cee zero

85
00:04:09.960 --> 00:04:12.319
<v Speaker 2>before A can update it. Thread B also reads it

86
00:04:12.319 --> 00:04:15.199
<v Speaker 2>ce zero. Then thread A adds one and writes one back.

87
00:04:15.479 --> 00:04:17.800
<v Speaker 2>Then thread B adds one to the zero at red

88
00:04:17.839 --> 00:04:18.839
<v Speaker 2>and writes one back.

89
00:04:19.040 --> 00:04:22.199
<v Speaker 1>Ah. So even though two threads incremented, the result is

90
00:04:22.240 --> 00:04:24.879
<v Speaker 1>one not two. Because they race to read the old

91
00:04:24.959 --> 00:04:25.959
<v Speaker 1>value exactly.

92
00:04:25.959 --> 00:04:28.360
<v Speaker 2>They tripped over each other and the result is wrong.

93
00:04:28.800 --> 00:04:32.000
<v Speaker 2>You can also get liveness issues like deadlock. That's where

94
00:04:32.160 --> 00:04:34.680
<v Speaker 2>thread A is waiting for a lock held by thread B,

95
00:04:35.079 --> 00:04:36.959
<v Speaker 2>and thread B is waiting for a lock held by.

96
00:04:36.920 --> 00:04:38.399
<v Speaker 1>Thread A like a gridlock.

97
00:04:38.759 --> 00:04:41.480
<v Speaker 2>Nobody can move precisely, stuck forever.

98
00:04:41.639 --> 00:04:45.439
<v Speaker 1>And Android adds its own specific wrinkles to these concurrency problems.

99
00:04:45.519 --> 00:04:48.040
<v Speaker 2>It sure does. The activity life cycle is probably the

100
00:04:48.040 --> 00:04:50.600
<v Speaker 2>biggest one. So you spin up a background thread and

101
00:04:50.639 --> 00:04:53.279
<v Speaker 2>it holds a direct reference to your activity or maybe

102
00:04:53.279 --> 00:04:55.600
<v Speaker 2>one of its views. Okay, now the user rotates to

103
00:04:55.639 --> 00:04:58.439
<v Speaker 2>the phone, The system destroys the old activity instance and

104
00:04:58.480 --> 00:05:00.839
<v Speaker 2>creates a new one. But your background thread might still

105
00:05:00.879 --> 00:05:03.600
<v Speaker 2>be chugging along holding onto that reference to the old

106
00:05:03.720 --> 00:05:05.120
<v Speaker 2>now dead activity, and that.

107
00:05:05.079 --> 00:05:08.279
<v Speaker 1>Means the old activity can't be garbage collected exactly.

108
00:05:08.439 --> 00:05:11.560
<v Speaker 2>Instant memory leak because something still has a grip on it.

109
00:05:11.639 --> 00:05:15.279
<v Speaker 1>Ooh, memory leaks the bane of mobile development, they really are.

110
00:05:15.839 --> 00:05:18.639
<v Speaker 2>And then there's the whole synchronization challenge. Your background thread

111
00:05:18.639 --> 00:05:20.800
<v Speaker 2>does its work, it's a result, great, but how do

112
00:05:20.839 --> 00:05:23.600
<v Speaker 2>you get that result back to the UI. You must

113
00:05:23.720 --> 00:05:27.120
<v Speaker 2>update UI elements on the main thread, right, So getting

114
00:05:27.240 --> 00:05:30.439
<v Speaker 2>data safely from the background thread to the main thread

115
00:05:30.759 --> 00:05:33.920
<v Speaker 2>is a fundamental problem that the Android toolkit is designed

116
00:05:33.920 --> 00:05:34.680
<v Speaker 2>to help solve.

117
00:05:34.920 --> 00:05:38.519
<v Speaker 1>Okay, so this is why Android provides these specific asynchronous

118
00:05:38.560 --> 00:05:42.160
<v Speaker 1>tools to give us safer managed ways to deal with threads,

119
00:05:42.360 --> 00:05:44.560
<v Speaker 1>life cycle issues, and UI updates.

120
00:05:44.639 --> 00:05:47.360
<v Speaker 2>That's the core idea. Instead of just dealing with raw

121
00:05:47.480 --> 00:05:50.040
<v Speaker 2>JABA threads and hoping for the best, you use these

122
00:05:50.160 --> 00:05:53.560
<v Speaker 2>higher level building blocks, which brings us neatly to the

123
00:05:53.560 --> 00:05:54.480
<v Speaker 2>toolkit itself.

124
00:05:54.839 --> 00:05:58.000
<v Speaker 1>Let's walk through that toolkit then, following the source. First

125
00:05:58.040 --> 00:05:59.759
<v Speaker 1>up is the one everyone seems to know. Maybe the

126
00:05:59.800 --> 00:06:01.839
<v Speaker 1>post child acinc tasks.

127
00:06:01.879 --> 00:06:05.120
<v Speaker 2>Ah, Yes, good old acinc task introduce way back in

128
00:06:05.199 --> 00:06:08.000
<v Speaker 2>API three, specifically to make it easier to do short

129
00:06:08.040 --> 00:06:11.000
<v Speaker 2>background tasks and get results back to the UI. It's

130
00:06:11.079 --> 00:06:13.360
<v Speaker 2>really a helper class for that common pattern, and.

131
00:06:13.360 --> 00:06:16.879
<v Speaker 1>It uses that specific structure of callback methods right, each

132
00:06:17.000 --> 00:06:18.839
<v Speaker 1>running on a particular thread.

133
00:06:18.920 --> 00:06:21.439
<v Speaker 2>Correct, you've got on pre execute, which runs first on

134
00:06:21.480 --> 00:06:24.639
<v Speaker 2>the main thread. Good for setting things up like showing

135
00:06:24.680 --> 00:06:28.639
<v Speaker 2>a progress spinner. Then the main work course do in background.

136
00:06:28.639 --> 00:06:30.759
<v Speaker 2>This runs on a background thread. This is where your

137
00:06:30.800 --> 00:06:33.959
<v Speaker 2>slow operation goes, and critically, you cannot touch the UI

138
00:06:34.079 --> 00:06:35.360
<v Speaker 2>directly from here.

139
00:06:35.319 --> 00:06:38.879
<v Speaker 1>Right, But what if you need to show progress, like

140
00:06:38.959 --> 00:06:39.720
<v Speaker 1>for a download.

141
00:06:39.920 --> 00:06:41.920
<v Speaker 2>That's what published progress is for. You call it from

142
00:06:42.040 --> 00:06:45.160
<v Speaker 2>inside do in background and that triggers it triggers on

143
00:06:45.240 --> 00:06:47.639
<v Speaker 2>progress update, which runs back on the main thread, so

144
00:06:47.680 --> 00:06:50.519
<v Speaker 2>you can safely update your progress bar or.

145
00:06:50.319 --> 00:06:53.240
<v Speaker 1>A text view makes sense. And when do in background.

146
00:06:52.920 --> 00:06:55.879
<v Speaker 2>Finishes, it returns a result which gets passed to on

147
00:06:56.000 --> 00:06:59.319
<v Speaker 2>post execute, and on post execute also runs on the

148
00:06:59.319 --> 00:07:02.879
<v Speaker 2>main thread, perfect for hiding the spinner showing the final data,

149
00:07:03.000 --> 00:07:03.839
<v Speaker 2>updating the UI.

150
00:07:04.079 --> 00:07:06.480
<v Speaker 1>And there's non canceled too if the task gets canceled

151
00:07:06.519 --> 00:07:07.240
<v Speaker 1>before finishing.

152
00:07:07.480 --> 00:07:11.199
<v Speaker 2>Yep, and a really key thing to remember. Each acing

153
00:07:11.240 --> 00:07:14.879
<v Speaker 2>task object is single use. You create it, you execute

154
00:07:14.879 --> 00:07:16.959
<v Speaker 2>it once, and that's it. You can't reuse it.

155
00:07:17.199 --> 00:07:20.800
<v Speaker 1>Now. You mentioned earlier that how acing task runs tasks

156
00:07:20.839 --> 00:07:23.279
<v Speaker 1>concurrently or one after another has changed over time. That

157
00:07:23.360 --> 00:07:24.800
<v Speaker 1>sounds potentially confusing.

158
00:07:24.959 --> 00:07:27.199
<v Speaker 2>Slight chuckle. Yeah, it's got a bit of a history.

159
00:07:27.680 --> 00:07:32.120
<v Speaker 2>Originally API three it executed tasks serially, one at a time.

160
00:07:32.639 --> 00:07:35.600
<v Speaker 2>Then in API four they switched it to run concurrently

161
00:07:36.079 --> 00:07:38.319
<v Speaker 2>using a thread pool that could handle like up to

162
00:07:38.360 --> 00:07:40.040
<v Speaker 2>one hundred and twenty eight tasks at once.

163
00:07:40.160 --> 00:07:41.600
<v Speaker 1>Oh, that's a big change.

164
00:07:41.439 --> 00:07:45.399
<v Speaker 2>Huge, and it caused problems because developers often implicitly relied

165
00:07:45.439 --> 00:07:49.120
<v Speaker 2>on the old serial behavior. So from API eleven onwards

166
00:07:49.279 --> 00:07:52.560
<v Speaker 2>they switched it back. The default execute method now runs

167
00:07:52.600 --> 00:07:53.839
<v Speaker 2>tasks serially again.

168
00:07:54.000 --> 00:07:57.000
<v Speaker 1>Okay, so the tricky period is really API four through ten,

169
00:07:57.120 --> 00:08:00.639
<v Speaker 1>where just calling execute might give you unexpected concurrency.

170
00:08:00.759 --> 00:08:03.319
<v Speaker 2>Exactly. That's the danger zone. If you need explicit control,

171
00:08:03.360 --> 00:08:05.759
<v Speaker 2>you should use execute on executor. You can pass it

172
00:08:05.879 --> 00:08:08.839
<v Speaker 2>acing task dop threadpool executor to get the concurrent behavior,

173
00:08:09.199 --> 00:08:13.199
<v Speaker 2>or acing test serial executor to force serial execution regardless

174
00:08:13.199 --> 00:08:14.120
<v Speaker 2>of the API level.

175
00:08:14.279 --> 00:08:17.560
<v Speaker 1>So the advice is target API eleven or higher if

176
00:08:17.600 --> 00:08:20.399
<v Speaker 1>you can test carefully on older versions, or maybe even

177
00:08:20.680 --> 00:08:23.759
<v Speaker 1>reimplement it yourself if you need absolute consistency.

178
00:08:23.959 --> 00:08:26.040
<v Speaker 2>Those are the main options. The source lays out.

179
00:08:26.120 --> 00:08:29.800
<v Speaker 1>Yeah, okay, beyond the concurrency history, what are the other

180
00:08:30.040 --> 00:08:33.679
<v Speaker 1>common traps with acing task? I feel like I've run

181
00:08:33.679 --> 00:08:36.000
<v Speaker 1>into issues using them inside activities before.

182
00:08:36.200 --> 00:08:40.159
<v Speaker 2>Ah. Yes, the activity life cycle strikes again. This is

183
00:08:40.200 --> 00:08:43.720
<v Speaker 2>probably the most common pitfall. If you declare your acing

184
00:08:43.799 --> 00:08:47.240
<v Speaker 2>task as a regular inner class or an anonymous inner

185
00:08:47.240 --> 00:08:49.759
<v Speaker 2>class inside your activity.

186
00:08:49.279 --> 00:08:52.000
<v Speaker 1>It automatically gets a reference to the activity instance.

187
00:08:51.720 --> 00:08:55.360
<v Speaker 2>Right, precisely an implicit strong reference because it often needs

188
00:08:55.440 --> 00:08:57.720
<v Speaker 2>to call activity methods or update views.

189
00:08:57.840 --> 00:08:59.759
<v Speaker 1>But if the user rotates, the screen.

190
00:09:00.000 --> 00:09:02.639
<v Speaker 2>System destroys the old activity and creates a new one.

191
00:09:02.679 --> 00:09:05.159
<v Speaker 2>But your acing task might still be running in the background,

192
00:09:05.279 --> 00:09:08.720
<v Speaker 2>holding onto that reference to the old destroyed activity.

193
00:09:08.320 --> 00:09:12.600
<v Speaker 1>Preventing it from being garbage collected memory. Leak city population.

194
00:09:12.120 --> 00:09:15.440
<v Speaker 2>You exactly leak city. So how do you fight that? Well?

195
00:09:15.440 --> 00:09:18.200
<v Speaker 1>Can't you just call cancel on the acing task and

196
00:09:18.240 --> 00:09:19.840
<v Speaker 1>the activities on destroy.

197
00:09:19.600 --> 00:09:22.639
<v Speaker 2>Or something you definitely should call cancel, maybe an on

198
00:09:22.879 --> 00:09:25.720
<v Speaker 2>pause or on destroy. It signals the task that it

199
00:09:25.720 --> 00:09:29.200
<v Speaker 2>should stop on canceled gets called instead of on post execute.

200
00:09:29.480 --> 00:09:31.200
<v Speaker 2>But cancel is just a request.

201
00:09:31.919 --> 00:09:34.720
<v Speaker 1>It doesn't magically stop the doing background method.

202
00:09:35.039 --> 00:09:38.440
<v Speaker 2>No, your code inside doing background needs to periodically check

203
00:09:38.480 --> 00:09:41.759
<v Speaker 2>that is canceled flag and actually stop doing work if

204
00:09:41.759 --> 00:09:45.440
<v Speaker 2>it's true. So cancelation helps, but it might not prevent

205
00:09:45.480 --> 00:09:47.519
<v Speaker 2>the leak if the task takes a while to notice

206
00:09:47.559 --> 00:09:49.840
<v Speaker 2>it's been canceled and the activity is already gone.

207
00:09:50.080 --> 00:09:53.799
<v Speaker 1>Okay, So cancelation is good hygiene, but not a perfect

208
00:09:53.840 --> 00:09:57.080
<v Speaker 1>leak prevention. What's the more robust solution? The book talks about.

209
00:09:56.960 --> 00:09:59.320
<v Speaker 2>Using what's called a retained headless fragment.

210
00:09:59.639 --> 00:10:01.320
<v Speaker 1>Okay, that sounds complicated.

211
00:10:01.440 --> 00:10:03.840
<v Speaker 2>It sounds worse than it is. The idea is pretty neat.

212
00:10:03.840 --> 00:10:05.799
<v Speaker 2>You create a fragment, but it doesn't have any UI,

213
00:10:05.960 --> 00:10:09.919
<v Speaker 2>it's headless, and you call set retain instance true on it.

214
00:10:09.960 --> 00:10:11.360
<v Speaker 1>What is set retain instance true.

215
00:10:11.480 --> 00:10:14.279
<v Speaker 2>It tells the system when the activity is destroyed and

216
00:10:14.320 --> 00:10:18.279
<v Speaker 2>recreated due to a configuration change like rotation, keep this

217
00:10:18.360 --> 00:10:21.720
<v Speaker 2>fragment instance alive. Don't destroy and recreate it.

218
00:10:21.919 --> 00:10:26.679
<v Speaker 1>Ah, so the fragment survives the rotation unlike the activity exactly.

219
00:10:26.919 --> 00:10:30.360
<v Speaker 2>You host your assing task inside this retain fragment. The

220
00:10:30.399 --> 00:10:33.399
<v Speaker 2>fragment can then hold onto the task safely. When the

221
00:10:33.440 --> 00:10:37.000
<v Speaker 2>new activity instance is created, the fragment reattaches to it.

222
00:10:37.200 --> 00:10:39.440
<v Speaker 1>And how does the fragment talk to the activity? Then?

223
00:10:39.799 --> 00:10:43.600
<v Speaker 2>Typically using an interface? The activity implements the interface like

224
00:10:43.720 --> 00:10:47.159
<v Speaker 2>task callbacks. The fragment gets a reference to the activity

225
00:10:47.200 --> 00:10:50.440
<v Speaker 2>and it's on attached method checks if it implements the interface,

226
00:10:50.480 --> 00:10:53.360
<v Speaker 2>and stores it, often as a weak reference just to

227
00:10:53.360 --> 00:10:57.080
<v Speaker 2>be extra safe, though less critical here than with handlers.

228
00:10:57.600 --> 00:11:01.519
<v Speaker 2>It detaches an on detach. The task running inside the

229
00:11:01.559 --> 00:11:04.559
<v Speaker 2>fragment can then call back to the currently attached activity

230
00:11:04.639 --> 00:11:05.440
<v Speaker 2>via the fragment.

231
00:11:05.679 --> 00:11:08.399
<v Speaker 1>So the fragment acts like a stable, surviving container for

232
00:11:08.440 --> 00:11:11.679
<v Speaker 1>the task, decoupling it from the activity's messy life cycle.

233
00:11:11.720 --> 00:11:15.360
<v Speaker 2>Precisely. It's a much safer pattern for managing acing tasks

234
00:11:15.440 --> 00:11:18.080
<v Speaker 2>tied to activities, and it's available in the support library,

235
00:11:18.120 --> 00:11:19.120
<v Speaker 2>so it works way back.

236
00:11:19.320 --> 00:11:22.879
<v Speaker 1>That's really clever. So bottom line for acing task. Good

237
00:11:22.960 --> 00:11:26.039
<v Speaker 1>for simple short background jobs closely tied to the UI,

238
00:11:26.480 --> 00:11:29.559
<v Speaker 1>especially needing progress updates. But watch out for leaks and

239
00:11:29.639 --> 00:11:31.639
<v Speaker 1>use that retained fragment pattern if needed.

240
00:11:31.799 --> 00:11:35.919
<v Speaker 2>Yep, that's a good summary. Now, moving deeper into the toolkit,

241
00:11:36.039 --> 00:11:39.639
<v Speaker 2>the source introduces handler and handler thread. These are more

242
00:11:39.679 --> 00:11:43.240
<v Speaker 2>like the fundamental building blocks. In fact, acinc task uses

243
00:11:43.320 --> 00:11:44.639
<v Speaker 2>handlers under the hood.

244
00:11:44.879 --> 00:11:48.440
<v Speaker 1>Okay, handlers, This involves the looper right, What exactly is

245
00:11:48.480 --> 00:11:48.879
<v Speaker 1>a looper?

246
00:11:49.000 --> 00:11:51.600
<v Speaker 2>A looper is basically a message loop for a thread.

247
00:11:52.000 --> 00:11:54.360
<v Speaker 2>A thread associated with a leaper runs a loop that

248
00:11:54.399 --> 00:11:57.919
<v Speaker 2>continuously checks a message queue. If there's a message or

249
00:11:57.960 --> 00:12:00.679
<v Speaker 2>a task like a runnable in the quy you, the

250
00:12:00.720 --> 00:12:03.200
<v Speaker 2>looper pulls it out and processes it. And the key

251
00:12:03.240 --> 00:12:05.559
<v Speaker 2>thing is key thing is the main thread and Android

252
00:12:05.639 --> 00:12:08.080
<v Speaker 2>already has a looper running on it. That's how it

253
00:12:08.120 --> 00:12:11.799
<v Speaker 2>processes UI events, drawing updates and everything else. It's constantly

254
00:12:11.879 --> 00:12:13.039
<v Speaker 2>checking its message queue.

255
00:12:13.120 --> 00:12:15.720
<v Speaker 1>Okay, so the main thread is just a special thread

256
00:12:15.759 --> 00:12:18.159
<v Speaker 1>that happens to have this built in message processing loop.

257
00:12:18.240 --> 00:12:20.440
<v Speaker 2>You got it. And a handler is an object you

258
00:12:20.480 --> 00:12:23.799
<v Speaker 2>create that's bound to a specific looper and therefore to

259
00:12:23.919 --> 00:12:25.240
<v Speaker 2>that looper's thread.

260
00:12:25.080 --> 00:12:27.639
<v Speaker 1>Bound to the looper, so bound to the thread essentially.

261
00:12:27.759 --> 00:12:30.639
<v Speaker 2>Yes, The handler gives you a way to post tasks

262
00:12:30.679 --> 00:12:34.120
<v Speaker 2>onto that specific threads message queue. You can call handler

263
00:12:34.120 --> 00:12:37.279
<v Speaker 2>dot post runnable or handler dot send message message.

264
00:12:37.519 --> 00:12:39.720
<v Speaker 1>Ah. So if I create a handler on the main

265
00:12:39.840 --> 00:12:43.320
<v Speaker 1>thread which automatically binds it to the main threads looper,

266
00:12:44.080 --> 00:12:47.360
<v Speaker 1>I can then pass that handler object to a background

267
00:12:47.360 --> 00:12:50.559
<v Speaker 1>thread exactly, and the background thread can use it, say

268
00:12:50.600 --> 00:12:54.039
<v Speaker 1>main thread handler dot post some runnable and some runnable

269
00:12:54.200 --> 00:12:56.759
<v Speaker 1>will get added to the main threads queue and eventually

270
00:12:56.840 --> 00:12:57.720
<v Speaker 1>run on the main thread.

271
00:12:57.840 --> 00:13:00.879
<v Speaker 2>That's the core mechanism. It's the stamp way to get

272
00:13:00.919 --> 00:13:03.679
<v Speaker 2>results or UI updates from a background thread back to

273
00:13:03.720 --> 00:13:07.000
<v Speaker 2>the main thread safely. Your background thread does its calculation,

274
00:13:07.240 --> 00:13:10.240
<v Speaker 2>then posts the runnable via the main thread handler to

275
00:13:10.360 --> 00:13:11.799
<v Speaker 2>update a text view or.

276
00:13:11.759 --> 00:13:14.799
<v Speaker 1>Whatever, and that explains methods like post delayed too just

277
00:13:14.840 --> 00:13:17.039
<v Speaker 1>adds it to the queue to be run later right.

278
00:13:16.960 --> 00:13:19.279
<v Speaker 2>Post delayed, post out time, post out front of queue.

279
00:13:19.360 --> 00:13:21.600
<v Speaker 2>They all just manipulate how and when the task gets

280
00:13:21.639 --> 00:13:25.039
<v Speaker 2>added to the target threads message queue and activity dot

281
00:13:25.120 --> 00:13:28.480
<v Speaker 2>run on UI thread. Runnable is basically just a shortcut

282
00:13:28.559 --> 00:13:30.720
<v Speaker 2>for getting a handler for the main thread and posting

283
00:13:30.759 --> 00:13:31.519
<v Speaker 2>your runnable to it.

284
00:13:31.639 --> 00:13:34.000
<v Speaker 1>What about sending message objects instead of runables?

285
00:13:34.399 --> 00:13:37.720
<v Speaker 2>Messages are an alternative way to send work. They're often

286
00:13:37.799 --> 00:13:40.720
<v Speaker 2>better if you need to pass structured data along with

287
00:13:40.799 --> 00:13:44.159
<v Speaker 2>the request. A message object has fields like what, an

288
00:13:44.240 --> 00:13:47.159
<v Speaker 2>integer code for the message type arge one, arch two,

289
00:13:47.279 --> 00:13:49.480
<v Speaker 2>and objection for arbitrary data.

290
00:13:49.519 --> 00:13:51.519
<v Speaker 1>So you define different message types.

291
00:13:51.240 --> 00:13:54.240
<v Speaker 2>With what yeah, and then in your handler instead of

292
00:13:54.279 --> 00:13:58.960
<v Speaker 2>just posting runnables, you override the handle message message msg method.

293
00:13:59.440 --> 00:14:02.480
<v Speaker 2>Inside that method, you typically have a switch statement based

294
00:14:02.519 --> 00:14:05.120
<v Speaker 2>on msg doob what to decide how to process different

295
00:14:05.159 --> 00:14:08.559
<v Speaker 2>kinds of messages. The source also points out using message

296
00:14:08.600 --> 00:14:11.960
<v Speaker 2>dot obtain to reuse message objects from a system pool,

297
00:14:11.960 --> 00:14:14.399
<v Speaker 2>which is more efficient than creating new message every time.

298
00:14:14.519 --> 00:14:16.399
<v Speaker 1>Okay, and handler thread? What's that for?

299
00:14:16.679 --> 00:14:19.679
<v Speaker 2>Handler thread? Is just a convenience class provided by the SDK.

300
00:14:20.039 --> 00:14:23.519
<v Speaker 2>It's basically a standard Java thread subclass that automatically sets

301
00:14:23.600 --> 00:14:25.240
<v Speaker 2>up a looper on itself when it starts.

302
00:14:25.279 --> 00:14:27.480
<v Speaker 1>Ah, so it gives you a ready made background thread

303
00:14:27.480 --> 00:14:29.679
<v Speaker 1>that already has its own message Q and looper.

304
00:14:29.960 --> 00:14:32.720
<v Speaker 2>Exactly. You start the handler thread, get its looper, create

305
00:14:32.720 --> 00:14:35.120
<v Speaker 2>a handler bound to that looper, and now you have

306
00:14:35.200 --> 00:14:38.440
<v Speaker 2>an easy way to post tasks to run sequentially on

307
00:14:38.480 --> 00:14:41.840
<v Speaker 2>that specific background thread. It's really useful if you need

308
00:14:42.039 --> 00:14:44.639
<v Speaker 2>a dedicated worker thread for a series of tasks like

309
00:14:44.720 --> 00:14:46.320
<v Speaker 2>processing sensor data or something.

310
00:14:46.480 --> 00:14:50.200
<v Speaker 1>Do handlers have the same memory leak problems as async

311
00:14:50.279 --> 00:14:52.879
<v Speaker 1>tasks if you're not careful like using them as inner

312
00:14:52.879 --> 00:14:53.960
<v Speaker 1>classes in inactivity?

313
00:14:54.000 --> 00:14:57.639
<v Speaker 2>Oh? Absolutely, same exact problem. A non static inner handler

314
00:14:57.679 --> 00:15:01.440
<v Speaker 2>class holds an implicit reference to the outer activity. If

315
00:15:01.480 --> 00:15:04.080
<v Speaker 2>you post a delayed message or runnable to that handler

316
00:15:04.320 --> 00:15:07.639
<v Speaker 2>and the activity gets destroyed before the message is processed.

317
00:15:07.240 --> 00:15:10.480
<v Speaker 1>The handler and its pending message keep the old activity

318
00:15:10.480 --> 00:15:12.120
<v Speaker 1>alive leak yep.

319
00:15:12.840 --> 00:15:16.279
<v Speaker 2>So the solution is identical. Make your handler subclass static

320
00:15:16.559 --> 00:15:18.480
<v Speaker 2>if it needs to talk back to the activity or

321
00:15:18.519 --> 00:15:21.759
<v Speaker 2>its views, pass the activity context to it, and store

322
00:15:21.759 --> 00:15:22.759
<v Speaker 2>it in a weak reference.

323
00:15:22.919 --> 00:15:25.480
<v Speaker 1>Use weak reference so the garbage collector can still reclaim

324
00:15:25.480 --> 00:15:27.120
<v Speaker 1>the activity if nothing else holds.

325
00:15:26.919 --> 00:15:30.679
<v Speaker 2>It strongly exactly, and typically you'd have methods like attach

326
00:15:30.799 --> 00:15:34.759
<v Speaker 2>activity and detach in your static handler class to set

327
00:15:34.799 --> 00:15:37.440
<v Speaker 2>and clear that weak reference as the activity comes and

328
00:15:37.480 --> 00:15:39.320
<v Speaker 2>goes standard safe pattern.

329
00:15:39.799 --> 00:15:43.840
<v Speaker 1>Okay, So handlers and handler threads offer more fundamental control

330
00:15:43.919 --> 00:15:47.320
<v Speaker 1>over threading and message passing. Good for when async task

331
00:15:47.399 --> 00:15:50.159
<v Speaker 1>is too simple where you need fine grain control or

332
00:15:50.159 --> 00:15:52.039
<v Speaker 1>communication between arbitrary threads.

333
00:15:52.120 --> 00:15:54.960
<v Speaker 2>That's a great way to put it. More control, more flexibility,

334
00:15:54.960 --> 00:15:58.000
<v Speaker 2>but also requires a bit more care with life cycle management.

335
00:15:58.120 --> 00:16:00.960
<v Speaker 1>All right, Moving on in the toolkit. The next major

336
00:16:01.000 --> 00:16:04.360
<v Speaker 1>piece the source covers is the loader framework. This sounds

337
00:16:04.360 --> 00:16:06.679
<v Speaker 1>specifically data oriented.

338
00:16:06.279 --> 00:16:10.320
<v Speaker 2>It absolutely is. Loaders are designed primarily for asynchronously loading

339
00:16:10.399 --> 00:16:13.080
<v Speaker 2>data that's going to be displayed in UI components, especially

340
00:16:13.159 --> 00:16:15.440
<v Speaker 2>things like list views or recycler views.

341
00:16:15.519 --> 00:16:19.480
<v Speaker 1>Asynchronously loading data. Okay, well, what's their killer feature? Why

342
00:16:19.559 --> 00:16:21.600
<v Speaker 1>use them over, say, an async task?

343
00:16:21.960 --> 00:16:24.840
<v Speaker 2>Their main advantage is how they integrate with the activity

344
00:16:24.879 --> 00:16:29.240
<v Speaker 2>and fragment life cycle. They automatically handle things like configuration changes,

345
00:16:29.559 --> 00:16:34.320
<v Speaker 2>screen rotations, and can efficiently cache data and deliver updates

346
00:16:34.360 --> 00:16:37.159
<v Speaker 2>without you having to manually manage all the state restoration.

347
00:16:37.639 --> 00:16:41.519
<v Speaker 1>Ah. So they solve that reload data on rotation problem.

348
00:16:41.559 --> 00:16:44.279
<v Speaker 2>That they do it beautifully. The core component is the

349
00:16:44.320 --> 00:16:46.480
<v Speaker 2>loader manager. You get an instance of it from your

350
00:16:46.519 --> 00:16:50.559
<v Speaker 2>activity or fragment. The loader manager is responsible for managing

351
00:16:50.559 --> 00:16:52.519
<v Speaker 2>the life cycle of your loader.

352
00:16:52.279 --> 00:16:54.440
<v Speaker 1>Instances and how do you interact with it.

353
00:16:54.639 --> 00:16:58.759
<v Speaker 2>Your activity or fragment implements an interface called loadermanager dot

354
00:16:58.799 --> 00:17:02.120
<v Speaker 2>loader callbacks. This has three methods you need to implement.

355
00:17:02.200 --> 00:17:03.000
<v Speaker 1>Okay, what are they?

356
00:17:03.080 --> 00:17:05.599
<v Speaker 2>First is on create loader. This is called by the

357
00:17:05.680 --> 00:17:08.880
<v Speaker 2>loader manager when you initialize a loader using in it

358
00:17:08.920 --> 00:17:11.920
<v Speaker 2>loader or restart loader. Your job here is just to

359
00:17:11.960 --> 00:17:14.519
<v Speaker 2>create and return the specific loader instance you.

360
00:17:14.480 --> 00:17:17.000
<v Speaker 1>Need, like a loader for database queries or maybe a

361
00:17:17.039 --> 00:17:18.519
<v Speaker 1>custom one exactly.

362
00:17:18.960 --> 00:17:22.119
<v Speaker 2>The second callback is onload finish. This is the important one.

363
00:17:22.599 --> 00:17:24.880
<v Speaker 2>It gets called on the main thread when the loader

364
00:17:24.880 --> 00:17:28.680
<v Speaker 2>has successfully finished loading its data. You receive that a

365
00:17:28.759 --> 00:17:32.319
<v Speaker 2>here and update your UI like populating an adapter. And

366
00:17:32.400 --> 00:17:35.920
<v Speaker 2>a third onloader reset This gets called when the loader

367
00:17:35.960 --> 00:17:38.839
<v Speaker 2>is being destroyed or reset. Your job here is to

368
00:17:38.880 --> 00:17:41.400
<v Speaker 2>clear out any references you might be holding to the

369
00:17:41.440 --> 00:17:44.720
<v Speaker 2>loader's data, so it can be garbage collected, for example

370
00:17:44.799 --> 00:17:47.480
<v Speaker 2>telling your adapter that the data is no longer valid.

371
00:17:47.880 --> 00:17:50.920
<v Speaker 1>So the loader manager orchestrates the loading, caching, and life

372
00:17:50.920 --> 00:17:54.759
<v Speaker 1>cycle awareness, and your activity fragment just plugs into these

373
00:17:54.799 --> 00:17:56.279
<v Speaker 1>specific life cycle points.

374
00:17:56.640 --> 00:17:59.079
<v Speaker 2>That's the idea. It abstracts away a lot of the

375
00:17:59.079 --> 00:18:01.839
<v Speaker 2>tricky life cycle management. If you need to create your

376
00:18:01.880 --> 00:18:05.160
<v Speaker 2>own custom loader. Acing taskloader is a common base.

377
00:18:04.920 --> 00:18:08.119
<v Speaker 1>Class to use ACM taskloader, so it uses acing tasks

378
00:18:08.240 --> 00:18:09.079
<v Speaker 1>in charge does.

379
00:18:09.359 --> 00:18:12.359
<v Speaker 2>It provides the basic structure you implement the loading background method.

380
00:18:12.440 --> 00:18:14.960
<v Speaker 2>That's where your actual data loading happens off the main thread.

381
00:18:15.319 --> 00:18:18.759
<v Speaker 2>The framework handles delivering the result via onload finished. It

382
00:18:18.799 --> 00:18:22.000
<v Speaker 2>also manages things like caching the result and only reloading

383
00:18:22.039 --> 00:18:23.759
<v Speaker 2>if the underlying data has changed.

384
00:18:24.039 --> 00:18:26.839
<v Speaker 1>The book gives an example. Right a thumbnail loader.

385
00:18:26.720 --> 00:18:31.400
<v Speaker 2>Yes, loading a bitmap thumbnail Loading background does the slow

386
00:18:31.480 --> 00:18:35.599
<v Speaker 2>work of decoding the image. Onload finished gets the bitmap

387
00:18:35.680 --> 00:18:38.440
<v Speaker 2>back on the main thread to display it. On start

388
00:18:38.440 --> 00:18:41.559
<v Speaker 2>loading checks if a cached version exists before starting the

389
00:18:41.599 --> 00:18:44.599
<v Speaker 2>load on reset would be where you might recycle the

390
00:18:44.640 --> 00:18:46.480
<v Speaker 2>bitmap if needed, and.

391
00:18:46.440 --> 00:18:49.200
<v Speaker 1>You kick things off using loadermanager dot in it loader

392
00:18:49.799 --> 00:18:52.720
<v Speaker 1>with some unique ID for each loader correct.

393
00:18:52.599 --> 00:18:56.440
<v Speaker 2>That ID links the netloader call to your specific implementation

394
00:18:56.599 --> 00:18:57.680
<v Speaker 2>of the loader callbacks.

395
00:18:57.759 --> 00:18:59.799
<v Speaker 1>What about cursor loader That seems like a really common

396
00:18:59.839 --> 00:19:00.160
<v Speaker 1>one one.

397
00:19:00.279 --> 00:19:04.599
<v Speaker 2>It's a specialized subclass of acyink taskloader designed specifically for

398
00:19:04.759 --> 00:19:09.599
<v Speaker 2>querying content providers, thin contacts, calendar data, or very commonly

399
00:19:09.839 --> 00:19:12.319
<v Speaker 2>the Media Store for images, music, et cetera.

400
00:19:12.759 --> 00:19:15.960
<v Speaker 1>So it handles queerying a database via a content provider.

401
00:19:16.079 --> 00:19:19.200
<v Speaker 2>Yes, And crucially it manages the cursor object that comes

402
00:19:19.200 --> 00:19:22.480
<v Speaker 2>back from the query. It handles opening it, closing it correctly,

403
00:19:22.519 --> 00:19:25.880
<v Speaker 2>and even automatically re querying if the underlying data in

404
00:19:25.920 --> 00:19:27.319
<v Speaker 2>the content provider changes.

405
00:19:27.440 --> 00:19:29.480
<v Speaker 1>Oh wow, So it watches for data changes too?

406
00:19:29.720 --> 00:19:32.519
<v Speaker 2>It can, Yes, and it works perfectly with adapters like

407
00:19:32.559 --> 00:19:34.839
<v Speaker 2>cursor adapter for displaying data and lists.

408
00:19:35.119 --> 00:19:37.920
<v Speaker 1>The Media store example in the book loading IMAX thumbnails

409
00:19:37.960 --> 00:19:40.920
<v Speaker 1>into a list really highlights the life cycle benefit, doesn't it.

410
00:19:40.960 --> 00:19:44.519
<v Speaker 1>You rotate the screen and boom, the data reappears almost

411
00:19:44.519 --> 00:19:47.880
<v Speaker 1>instantly because the cursor loader managed by the loader manager

412
00:19:48.160 --> 00:19:51.680
<v Speaker 1>survived the activity recreation. It just reconnects to the new

413
00:19:51.720 --> 00:19:55.359
<v Speaker 1>activity instance and delivers the already loaded cursor data straight

414
00:19:55.359 --> 00:19:58.000
<v Speaker 1>away in on load finished. No need to hit the

415
00:19:58.079 --> 00:20:00.000
<v Speaker 1>database again just because the screen rotator.

416
00:20:00.200 --> 00:20:03.480
<v Speaker 2>That is a massive user experience win and the book

417
00:20:03.519 --> 00:20:05.759
<v Speaker 2>mentioned combining loaders, Yeah.

418
00:20:05.519 --> 00:20:08.359
<v Speaker 1>A really powerful pattern. Imagine you use a cursor loader

419
00:20:08.680 --> 00:20:11.079
<v Speaker 1>to get a list of say image IDs from the

420
00:20:11.079 --> 00:20:15.519
<v Speaker 1>media store that populates your main list adapter. Then inside

421
00:20:15.559 --> 00:20:17.880
<v Speaker 1>your adapter's buy and view method where you set up

422
00:20:17.960 --> 00:20:21.640
<v Speaker 1>each list item view. As items become visible, you can

423
00:20:21.720 --> 00:20:25.559
<v Speaker 1>use the same loader manager to initialize separate individual thumbnail

424
00:20:25.599 --> 00:20:28.519
<v Speaker 1>loader instances using the image id is part of the

425
00:20:28.640 --> 00:20:32.480
<v Speaker 1>unique loader id for each specific thumbnail. Ah So one

426
00:20:32.559 --> 00:20:36.160
<v Speaker 1>main loader for the list structure, and then potentially many

427
00:20:36.240 --> 00:20:39.240
<v Speaker 1>smaller on demand loaders for the images within the.

428
00:20:39.279 --> 00:20:44.160
<v Speaker 2>Visible items exactly loading just what's needed asynchronously efficiently and

429
00:20:44.240 --> 00:20:47.119
<v Speaker 2>handling all the life cycle stuff automatically. It's a very

430
00:20:47.240 --> 00:20:50.400
<v Speaker 2>elegant solution for complex data displays.

431
00:20:50.799 --> 00:20:53.119
<v Speaker 1>So loaders are definitely the way to go for async

432
00:20:53.200 --> 00:20:56.799
<v Speaker 1>data loading tied to the UI, especially lists or grids

433
00:20:57.119 --> 00:21:01.079
<v Speaker 1>where surviving configuration changes and getting automatic updates is important.

434
00:21:01.119 --> 00:21:05.039
<v Speaker 2>Absolutely, especially when dealing with content providers via cursor loader.

435
00:21:05.160 --> 00:21:09.160
<v Speaker 1>All right, next tool intense service. The name suggests it's

436
00:21:09.160 --> 00:21:11.640
<v Speaker 1>related to services and intents it is.

437
00:21:11.759 --> 00:21:14.960
<v Speaker 2>It's a specific subclass of service designed for a particular

438
00:21:15.079 --> 00:21:19.519
<v Speaker 2>use case, running simple background tasks sequentially off the main

439
00:21:19.559 --> 00:21:22.319
<v Speaker 2>thread in a way that's decoupled from the UI and

440
00:21:22.359 --> 00:21:23.480
<v Speaker 2>guaranteed to complete.

441
00:21:23.519 --> 00:21:26.480
<v Speaker 1>Guaranteed to complete, Yeah, even if the user navigates away

442
00:21:26.480 --> 00:21:26.960
<v Speaker 1>from the app.

443
00:21:27.079 --> 00:21:30.359
<v Speaker 2>Yes, that's the key benefit. It's designed for operations that

444
00:21:30.400 --> 00:21:33.960
<v Speaker 2>need to finish reliably, like uploading a file or processing

445
00:21:33.960 --> 00:21:36.160
<v Speaker 2>some data in the background, regardless of what the user

446
00:21:36.200 --> 00:21:36.920
<v Speaker 2>is currently doing.

447
00:21:37.000 --> 00:21:37.720
<v Speaker 1>How does it work.

448
00:21:37.839 --> 00:21:40.720
<v Speaker 2>It uses a single background worker thread, a handworth thread

449
00:21:40.759 --> 00:21:44.039
<v Speaker 2>actually internally. When you want it to do some work,

450
00:21:44.279 --> 00:21:47.440
<v Speaker 2>you call start service with an intent containing any data

451
00:21:47.519 --> 00:21:48.359
<v Speaker 2>the task needs.

452
00:21:48.480 --> 00:21:51.200
<v Speaker 1>Okay, Sending an intent triggers the work right.

453
00:21:51.759 --> 00:21:55.200
<v Speaker 2>The intent service receives these intents in its on handle

454
00:21:55.319 --> 00:21:59.759
<v Speaker 2>intent intent method. This method runs on that background worker thread.

455
00:22:00.119 --> 00:22:03.400
<v Speaker 2>You put your actual background processing code inside on handle

456
00:22:03.440 --> 00:22:04.200
<v Speaker 2>intent and.

457
00:22:04.119 --> 00:22:07.319
<v Speaker 1>It processes them one by one like a queue exactly.

458
00:22:07.799 --> 00:22:11.400
<v Speaker 2>It maintains an internal queue of the incoming intents. It

459
00:22:11.440 --> 00:22:15.599
<v Speaker 2>processes one intent completely in on handle intent, then automatically

460
00:22:15.640 --> 00:22:18.039
<v Speaker 2>picks up the next one from the queue. When the

461
00:22:18.119 --> 00:22:21.279
<v Speaker 2>queue is empty, the intent service automatically stops itself.

462
00:22:21.359 --> 00:22:22.240
<v Speaker 1>Oh self stopping.

463
00:22:22.279 --> 00:22:25.160
<v Speaker 2>That's convenience very you don't need to manually manage its

464
00:22:25.160 --> 00:22:28.519
<v Speaker 2>life cycle as much. The source uses calculating the nth

465
00:22:28.559 --> 00:22:31.039
<v Speaker 2>prime number as a simple example task you'd put in

466
00:22:31.119 --> 00:22:31.920
<v Speaker 2>on handle intent.

467
00:22:32.279 --> 00:22:35.200
<v Speaker 1>Since it's decoupled from the activity that started it, how

468
00:22:35.200 --> 00:22:37.519
<v Speaker 1>do you get results back? You can't just return a

469
00:22:37.640 --> 00:22:38.319
<v Speaker 1>value from.

470
00:22:38.119 --> 00:22:41.480
<v Speaker 2>On handle intent, No, you need a different mechanism. One

471
00:22:41.559 --> 00:22:44.319
<v Speaker 2>common pattern described in the source is using a pending

472
00:22:44.359 --> 00:22:49.240
<v Speaker 2>intent the component starting the service. Say, an activity creates

473
00:22:49.279 --> 00:22:52.240
<v Speaker 2>a pending intent that wraps an intent targeted back at itself.

474
00:22:52.599 --> 00:22:55.039
<v Speaker 2>It puts this pending intent as an extra in the

475
00:22:55.079 --> 00:22:56.880
<v Speaker 2>intent used to start the service.

476
00:22:57.160 --> 00:22:59.519
<v Speaker 1>So you send a reply to address.

477
00:22:59.200 --> 00:23:03.079
<v Speaker 2>With the worker request kind of yeah, inside on handle intent.

478
00:23:03.200 --> 00:23:06.240
<v Speaker 2>Once the work is done, the intent service retrieves that

479
00:23:06.359 --> 00:23:10.960
<v Speaker 2>pending intent from the incoming intent and calls its send method,

480
00:23:11.359 --> 00:23:14.200
<v Speaker 2>passing back any result data in a result intent.

481
00:23:14.400 --> 00:23:16.000
<v Speaker 1>And where does that result intent arrive?

482
00:23:16.319 --> 00:23:19.039
<v Speaker 2>If the pending intent was created using activity dot create

483
00:23:19.039 --> 00:23:22.400
<v Speaker 2>pending result, the result arise back in the original activities

484
00:23:22.480 --> 00:23:26.000
<v Speaker 2>on activity result method. And this mechanism works even if

485
00:23:26.039 --> 00:23:29.160
<v Speaker 2>the activity was recreated, for example, due to rotation while

486
00:23:29.200 --> 00:23:30.119
<v Speaker 2>the service was running.

487
00:23:30.200 --> 00:23:32.480
<v Speaker 1>That's pretty neat. What are other ways to communicate results.

488
00:23:32.640 --> 00:23:36.119
<v Speaker 2>System notifications are very common, especially for longer tasks or

489
00:23:36.200 --> 00:23:38.000
<v Speaker 2>work that finishes when the app might not be in

490
00:23:38.039 --> 00:23:41.440
<v Speaker 2>the foreground. You just use notification compact, dot builder from

491
00:23:41.440 --> 00:23:45.119
<v Speaker 2>within on handle intent to post or updata. Notification makes

492
00:23:45.119 --> 00:23:48.240
<v Speaker 2>sense for things like upload complete exactly. You can also

493
00:23:48.359 --> 00:23:51.440
<v Speaker 2>use broadcasts, which we'll talk more about. With regular services,

494
00:23:51.920 --> 00:23:54.799
<v Speaker 2>the Intent service could broadcast an intent with the result

495
00:23:54.880 --> 00:23:57.920
<v Speaker 2>and any interested component with a registered broadcast receiver could

496
00:23:57.960 --> 00:24:01.480
<v Speaker 2>pick it up. For showing progress, notifications are again a

497
00:24:01.519 --> 00:24:05.000
<v Speaker 2>good fit. You can use notification Compact, dot builder dot

498
00:24:05.039 --> 00:24:08.799
<v Speaker 2>set progress to show a progress bar right in the notification.

499
00:24:09.200 --> 00:24:13.440
<v Speaker 1>Okay, so Intent service use it for reliable, sequential background

500
00:24:13.519 --> 00:24:17.039
<v Speaker 1>work that comes in as discrete requests. Intents needs to

501
00:24:17.039 --> 00:24:20.000
<v Speaker 1>finish even if the app isn't visible and doesn't require

502
00:24:20.079 --> 00:24:24.839
<v Speaker 1>complex concurrency like uploads, downloads, simple data processing jobs.

503
00:24:24.960 --> 00:24:29.000
<v Speaker 2>That's the sweet spot for Intent service, simple reliable, queued work.

504
00:24:29.160 --> 00:24:32.359
<v Speaker 1>But what if you need more flexibility, more control over threads,

505
00:24:32.519 --> 00:24:35.160
<v Speaker 1>or different ways to communicate. That brings us to the

506
00:24:35.240 --> 00:24:37.200
<v Speaker 1>base class the regular service.

507
00:24:37.440 --> 00:24:39.799
<v Speaker 2>Right a plane service gives you a component that can

508
00:24:39.880 --> 00:24:42.640
<v Speaker 2>run in the background independent of the UI, but it

509
00:24:42.680 --> 00:24:45.920
<v Speaker 2>doesn't provide that built in worker thread and queuing mechanism.

510
00:24:46.000 --> 00:24:49.000
<v Speaker 2>Like Intent service, you manage the threading yourself.

511
00:24:49.319 --> 00:24:52.799
<v Speaker 1>So if I need multiple background threads working in parallel

512
00:24:52.799 --> 00:24:53.960
<v Speaker 1>within my service.

513
00:24:53.799 --> 00:24:56.200
<v Speaker 2>Then a regular service is what you'd use. You would

514
00:24:56.200 --> 00:24:59.759
<v Speaker 2>typically create and manage your own thread pool inside the service,

515
00:25:00.240 --> 00:25:04.359
<v Speaker 2>maybe using Java's executor service framework like executors dot nufix

516
00:25:04.400 --> 00:25:04.920
<v Speaker 2>third pool.

517
00:25:05.319 --> 00:25:06.559
<v Speaker 1>And where would you start the work?

518
00:25:06.839 --> 00:25:09.680
<v Speaker 2>Usually in the on start command intent intent in flags

519
00:25:09.759 --> 00:25:12.519
<v Speaker 2>in started method. This gets called every time start service

520
00:25:12.640 --> 00:25:15.720
<v Speaker 2>is invoked. You'd take the task described by the intent

521
00:25:15.799 --> 00:25:19.039
<v Speaker 2>and submit it to your executor service. The source shows

522
00:25:19.079 --> 00:25:21.839
<v Speaker 2>a pattern where the service keeps track of active tasks

523
00:25:21.880 --> 00:25:25.759
<v Speaker 2>and calls stop self started only when all tasks associated

524
00:25:25.759 --> 00:25:27.640
<v Speaker 2>with a particular start command are complete.

525
00:25:27.759 --> 00:25:31.359
<v Speaker 1>So much more manual control over concurrency in life cycle exactly.

526
00:25:31.680 --> 00:25:34.640
<v Speaker 2>And because you have this flexibility, services also offer more

527
00:25:34.680 --> 00:25:37.799
<v Speaker 2>ways to communicate back to other components beyond the pending

528
00:25:37.839 --> 00:25:40.720
<v Speaker 2>intent notification options typical for Intent.

529
00:25:40.519 --> 00:25:42.240
<v Speaker 1>Service like what what are the alternatives?

530
00:25:42.480 --> 00:25:45.920
<v Speaker 2>One mechanism is using a messenger. This is based on handlers.

531
00:25:46.599 --> 00:25:49.839
<v Speaker 2>The client, like an activity, creates a handler, usually on

532
00:25:49.880 --> 00:25:52.799
<v Speaker 2>its main thread, to receive messages back from the service.

533
00:25:53.400 --> 00:25:56.039
<v Speaker 2>It wraps this handle in a messenger object and passes

534
00:25:56.039 --> 00:25:58.680
<v Speaker 2>the messenger to the service, maybe in the intent used

535
00:25:58.720 --> 00:26:00.799
<v Speaker 2>to start it or through so.

536
00:26:00.680 --> 00:26:03.720
<v Speaker 1>The activity sends the service away to message it back precisely.

537
00:26:04.240 --> 00:26:07.799
<v Speaker 2>The service can then use this client provided messenger to

538
00:26:07.960 --> 00:26:12.240
<v Speaker 2>send message objects back to the activities handler. These messages

539
00:26:12.279 --> 00:26:15.519
<v Speaker 2>are processed on the activity's main thread via its handler's

540
00:26:15.519 --> 00:26:18.720
<v Speaker 2>handle message method. Again, you need the static handler plus

541
00:26:18.720 --> 00:26:20.839
<v Speaker 2>week reference pattern in the activity.

542
00:26:20.359 --> 00:26:24.079
<v Speaker 1>For safety okay messenger for message based communication? What about

543
00:26:24.079 --> 00:26:25.599
<v Speaker 1>direct calls? Binding?

544
00:26:25.799 --> 00:26:29.799
<v Speaker 2>Binding is another major communication pattern for services. An activity

545
00:26:29.880 --> 00:26:32.920
<v Speaker 2>or other component can call bind service instead of start

546
00:26:32.960 --> 00:26:36.759
<v Speaker 2>service if the service allows binding. The system establishes a connection.

547
00:26:37.480 --> 00:26:40.880
<v Speaker 2>The activity receives a callback on service connected, which provides

548
00:26:40.920 --> 00:26:44.240
<v Speaker 2>it with a direct communication channel, usually an eyebinder interface

549
00:26:44.319 --> 00:26:45.480
<v Speaker 2>to the service, so.

550
00:26:45.440 --> 00:26:47.839
<v Speaker 1>The activity can then just call methods directly on the

551
00:26:47.880 --> 00:26:48.640
<v Speaker 1>service object.

552
00:26:48.920 --> 00:26:52.559
<v Speaker 2>Often yes, the ibinder returned by the service's on bind

553
00:26:52.599 --> 00:26:55.480
<v Speaker 2>method typically provides a way to get a direct reference

554
00:26:55.519 --> 00:26:58.440
<v Speaker 2>to the service instance itself, allowing the activity to call

555
00:26:58.480 --> 00:26:59.519
<v Speaker 2>public methods on it.

556
00:26:59.680 --> 00:27:02.279
<v Speaker 1>Sounds super convenient for tightly coupled interactions.

557
00:27:02.480 --> 00:27:07.480
<v Speaker 2>It is very efficient for local ongoing communication but big

558
00:27:07.519 --> 00:27:11.359
<v Speaker 2>warning sign memory leaks. If the service holds a strong

559
00:27:11.480 --> 00:27:14.960
<v Speaker 2>reference back to the bound activity etexample, to send callbacks,

560
00:27:15.160 --> 00:27:17.680
<v Speaker 2>you can easily create a leak if the activity is

561
00:27:17.720 --> 00:27:19.400
<v Speaker 2>destroyed while still bound.

562
00:27:19.519 --> 00:27:22.200
<v Speaker 1>So how do you do callbacks safely with a bound service?

563
00:27:22.559 --> 00:27:25.920
<v Speaker 2>The recommended pattern, again from the source, involves interfaces and

564
00:27:26.000 --> 00:27:30.319
<v Speaker 2>weak references. The activity implements a callback interface. When binding,

565
00:27:30.440 --> 00:27:33.720
<v Speaker 2>the activity passes itself as the callback listener to the service.

566
00:27:34.119 --> 00:27:36.640
<v Speaker 2>The service stores this listener only as a weak reference.

567
00:27:37.000 --> 00:27:39.440
<v Speaker 2>When the service needs to notify the client, it retrieves

568
00:27:39.440 --> 00:27:41.480
<v Speaker 2>the listener from the week reference, checking it's not in

569
00:27:41.519 --> 00:27:44.920
<v Speaker 2>all and calls the interface method. Often the service uses

570
00:27:44.920 --> 00:27:47.680
<v Speaker 2>an ACYNC task internally to do work and makes the

571
00:27:47.680 --> 00:27:50.000
<v Speaker 2>callback from on post execute to ensure it lands on

572
00:27:50.000 --> 00:27:50.640
<v Speaker 2>the main thread.

573
00:27:50.799 --> 00:27:54.960
<v Speaker 1>Okay, so weak reference is key again for safe binding callbacks.

574
00:27:55.279 --> 00:27:57.680
<v Speaker 1>Are there other options? Broadcasting?

575
00:27:57.920 --> 00:28:01.200
<v Speaker 2>Yes, Broadcasting is always an option. The service can simply

576
00:28:01.279 --> 00:28:04.960
<v Speaker 2>construct an intent with the results and broadcast it. Any

577
00:28:04.960 --> 00:28:08.640
<v Speaker 2>component interested can register a broadcast receiver to listen for

578
00:28:08.720 --> 00:28:09.559
<v Speaker 2>that intent.

579
00:28:09.559 --> 00:28:12.960
<v Speaker 1>And using local broadcast manager is better for broadcasts just

580
00:28:13.000 --> 00:28:13.920
<v Speaker 1>within your own app.

581
00:28:14.039 --> 00:28:17.279
<v Speaker 2>Definitely, it's more efficient and more secure as the broadcasts

582
00:28:17.400 --> 00:28:19.279
<v Speaker 2>don't leave your application process.

583
00:28:19.519 --> 00:28:22.599
<v Speaker 1>The source mentioned something about checking if anyone received a broadcast.

584
00:28:22.960 --> 00:28:27.240
<v Speaker 2>Ah yeah, using sen broadcast sync. Unlike the regular asynchronous

585
00:28:27.359 --> 00:28:30.119
<v Speaker 2>end broadcast, this one sends the broadcast and waits for

586
00:28:30.200 --> 00:28:34.240
<v Speaker 2>all receivers to process it before returning. Receivers can potentially

587
00:28:34.279 --> 00:28:37.480
<v Speaker 2>modify the result data or code. The service can check

588
00:28:37.480 --> 00:28:39.839
<v Speaker 2>if the broadcast was handled, for example, if the result

589
00:28:39.920 --> 00:28:43.039
<v Speaker 2>code changed. If not, maybe nobody was listening, so the

590
00:28:43.119 --> 00:28:46.599
<v Speaker 2>service could fall back to posting a notification instead. One

591
00:28:46.680 --> 00:28:50.160
<v Speaker 2>tricky point. Send broadcast sync runs on the calling thread,

592
00:28:50.279 --> 00:28:52.640
<v Speaker 2>so if your receiver needs the main thread, you might

593
00:28:52.720 --> 00:28:55.160
<v Speaker 2>need to call send broadcast sync from the main thread

594
00:28:55.160 --> 00:28:58.119
<v Speaker 2>within your service, or e g. From that acing tasks

595
00:28:58.160 --> 00:28:59.319
<v Speaker 2>on post execute again.

596
00:28:59.480 --> 00:29:02.799
<v Speaker 1>Lots of unication options with services, so use a regular

597
00:29:02.839 --> 00:29:06.559
<v Speaker 1>service when you need fine grained control over background threads, concurrency,

598
00:29:07.000 --> 00:29:10.119
<v Speaker 1>or when you need more complex ongoing interaction patterns like

599
00:29:10.160 --> 00:29:14.079
<v Speaker 1>binding or messengers. Things like music players or concurrent downloads.

600
00:29:14.079 --> 00:29:15.759
<v Speaker 1>Seem like prime candidate exactly.

601
00:29:15.839 --> 00:29:18.400
<v Speaker 2>More power, more flexibility, more responsibility.

602
00:29:18.559 --> 00:29:22.119
<v Speaker 1>Okay. Last tool in the main toolkit Alarm Manager. This

603
00:29:22.200 --> 00:29:24.119
<v Speaker 1>sounds like it's for scheduling things way out in the

604
00:29:24.119 --> 00:29:25.319
<v Speaker 1>future precisely.

605
00:29:25.799 --> 00:29:28.960
<v Speaker 2>Alarm manager is a system service that lets your applications

606
00:29:29.000 --> 00:29:31.319
<v Speaker 2>schedule code to be run at some point in future,

607
00:29:31.680 --> 00:29:34.720
<v Speaker 2>even if your application isn't currently running, or even if

608
00:29:34.759 --> 00:29:36.119
<v Speaker 2>the device is asleep.

609
00:29:36.559 --> 00:29:39.160
<v Speaker 1>Even if the device is asleep. How does that work?

610
00:29:39.279 --> 00:29:41.480
<v Speaker 2>Well, there are different types of alarms you can set.

611
00:29:41.559 --> 00:29:45.079
<v Speaker 2>They vary based on two main things, the clock they

612
00:29:45.200 --> 00:29:47.279
<v Speaker 2>use and whether they should wake the device up.

613
00:29:47.359 --> 00:29:48.640
<v Speaker 1>Okay, what are the clock types?

614
00:29:49.240 --> 00:29:52.920
<v Speaker 2>You have elapsic real time and RTC. Elapse Real time

615
00:29:53.039 --> 00:29:55.279
<v Speaker 2>is based on the time since the device lasts booted.

616
00:29:55.559 --> 00:29:58.359
<v Speaker 2>It ignores wall clock time and time zones, just counts

617
00:29:58.519 --> 00:30:02.559
<v Speaker 2>milliseconds since boot. RTC real time clock is based on

618
00:30:02.720 --> 00:30:04.400
<v Speaker 2>standard UTC wall clock time.

619
00:30:04.759 --> 00:30:06.960
<v Speaker 1>So lapse of drill time is good for run this

620
00:30:07.039 --> 00:30:09.799
<v Speaker 1>five minutes from now, and RTC is for run this

621
00:30:09.839 --> 00:30:10.839
<v Speaker 1>at two pm tomorrow.

622
00:30:11.119 --> 00:30:13.519
<v Speaker 2>Generally yes. And then for each of those clock tikes

623
00:30:13.559 --> 00:30:15.599
<v Speaker 2>you have a regular version and a wake up version.

624
00:30:15.640 --> 00:30:17.960
<v Speaker 2>What's the difference the regular versions? A lapse to real

625
00:30:18.000 --> 00:30:20.200
<v Speaker 2>time in RTC will only fire the alarm when the

626
00:30:20.200 --> 00:30:22.759
<v Speaker 2>device happens to be awake anyway for some other reason,

627
00:30:22.799 --> 00:30:25.400
<v Speaker 2>after the schedule time is passed. If the device is

628
00:30:25.440 --> 00:30:27.759
<v Speaker 2>asleep at the schedule time, the alarm is delayed until

629
00:30:27.759 --> 00:30:29.720
<v Speaker 2>it wakes up ah.

630
00:30:29.240 --> 00:30:32.440
<v Speaker 1>So they don't guarantee exact timing if the device is asleep.

631
00:30:32.559 --> 00:30:35.920
<v Speaker 2>Correct the wake up versions elapse A drill time wake

632
00:30:36.000 --> 00:30:39.160
<v Speaker 2>up and RTC awake up, however, will actively wake the

633
00:30:39.160 --> 00:30:42.599
<v Speaker 2>device's CPU up if necessary to deliver the alarm at

634
00:30:42.720 --> 00:30:43.880
<v Speaker 2>or near the scheduled time.

635
00:30:44.000 --> 00:30:46.799
<v Speaker 1>Got it wake up alarms use more battery.

636
00:30:46.440 --> 00:30:50.039
<v Speaker 2>Presumably significantly more yes, so you should only use them

637
00:30:50.039 --> 00:30:53.839
<v Speaker 2>when timely execution is critical. The source also mentions that

638
00:30:53.880 --> 00:30:57.759
<v Speaker 2>since API nineteen Kitcat, regular alarms set with set are

639
00:30:57.799 --> 00:30:59.000
<v Speaker 2>inexact by default.

640
00:30:59.079 --> 00:31:00.839
<v Speaker 1>Inexact. That mean the.

641
00:31:00.799 --> 00:31:03.759
<v Speaker 2>System might batch alarms from different apps together and shift

642
00:31:03.759 --> 00:31:07.720
<v Speaker 2>their delivery times slightly to save battery. If you absolutely

643
00:31:07.759 --> 00:31:10.319
<v Speaker 2>need an alarm to fire at a precise time. On

644
00:31:10.400 --> 00:31:13.839
<v Speaker 2>API nineteen plus Nature, you have to use set exact.

645
00:31:14.160 --> 00:31:17.160
<v Speaker 2>For repeating alarms, they're set in exact repeating, which is

646
00:31:17.240 --> 00:31:19.960
<v Speaker 2>preferred for battery life, and the older set repeating.

647
00:31:20.039 --> 00:31:22.000
<v Speaker 1>Okay, how do you cancel an alarm you've set?

648
00:31:22.119 --> 00:31:25.079
<v Speaker 2>You use the cancel method on the alarm manager, passing

649
00:31:25.160 --> 00:31:27.680
<v Speaker 2>in the exact same pending intent you use when you

650
00:31:27.720 --> 00:31:28.920
<v Speaker 2>originally set the alarm.

651
00:31:28.720 --> 00:31:30.440
<v Speaker 1>The pending intent has to match exactly.

652
00:31:30.720 --> 00:31:34.079
<v Speaker 2>Yes, the matching is done based on the intent inside

653
00:31:34.079 --> 00:31:38.039
<v Speaker 2>the pend intent. Using intent dot filter equals that checks

654
00:31:38.039 --> 00:31:41.079
<v Speaker 2>the action data type, category is, and component name, but

655
00:31:41.119 --> 00:31:44.440
<v Speaker 2>it notably ignores any extras in the intent. Also, if

656
00:31:44.480 --> 00:31:46.400
<v Speaker 2>you set a new alarm using a pending intent that

657
00:31:46.400 --> 00:31:49.359
<v Speaker 2>matches an existing one, the old one is automatically canceled.

658
00:31:49.440 --> 00:31:52.440
<v Speaker 1>Okay, so the alarm fires and it triggers the pending intent.

659
00:31:52.519 --> 00:31:54.400
<v Speaker 1>What can that pending intent actually do?

660
00:31:54.759 --> 00:31:57.000
<v Speaker 2>It can trigger one of three things, depending on how

661
00:31:57.039 --> 00:31:59.799
<v Speaker 2>you created it. Pending intent. Dot get activity launches an

662
00:31:59.799 --> 00:32:02.880
<v Speaker 2>ex activity, pending intent, dot get broadcast sends a broadcast,

663
00:32:03.279 --> 00:32:06.519
<v Speaker 2>and pending intent. Dot get service starts a service.

664
00:32:06.640 --> 00:32:10.200
<v Speaker 1>Launching an activity from an alarm sounds disruptive.

665
00:32:10.319 --> 00:32:13.680
<v Speaker 2>It usually is taking over the user screen unexpectedly isn't

666
00:32:13.680 --> 00:32:17.160
<v Speaker 2>great ux, So pending intent dot get activity for alarms

667
00:32:17.200 --> 00:32:18.160
<v Speaker 2>is pretty rare.

668
00:32:18.000 --> 00:32:19.759
<v Speaker 1>So it's usually a broadcast or a service.

669
00:32:19.920 --> 00:32:23.440
<v Speaker 2>Most commonly it's pending intent dot get broadcast. You create

670
00:32:23.440 --> 00:32:26.640
<v Speaker 2>a broadcast receiver to handle the alarm trigger. A big

671
00:32:26.680 --> 00:32:29.279
<v Speaker 2>advantage is that if your receiver is registered in the manifest,

672
00:32:29.319 --> 00:32:32.519
<v Speaker 2>statically the system can launch your app process just to

673
00:32:32.559 --> 00:32:35.519
<v Speaker 2>deliver the alarm broadcast, even if your app wasn't running.

674
00:32:35.720 --> 00:32:39.319
<v Speaker 1>Okay, but what can the broadcast receiver actually do? Did

675
00:32:39.400 --> 00:32:40.559
<v Speaker 1>you say they have time limits?

676
00:32:40.960 --> 00:32:44.039
<v Speaker 2>They do. The on receive method runs on the main

677
00:32:44.079 --> 00:32:47.160
<v Speaker 2>thread and typically has only about ten seconds before the

678
00:32:47.200 --> 00:32:50.000
<v Speaker 2>system might kill the process. So it's good for very

679
00:32:50.039 --> 00:32:53.440
<v Speaker 2>quick tasks like scheduling the next alarm or maybe posting

680
00:32:53.440 --> 00:32:54.079
<v Speaker 2>a notification.

681
00:32:54.279 --> 00:32:56.599
<v Speaker 1>Can you do background work? You mentioned go ACYNC before.

682
00:32:56.880 --> 00:33:00.599
<v Speaker 2>Yes. On API eleven plus APA A receive seiver can

683
00:33:00.640 --> 00:33:04.759
<v Speaker 2>call go async within on receive. This tells the system, hey,

684
00:33:04.799 --> 00:33:06.839
<v Speaker 2>I need a bit more time for background work. It

685
00:33:06.880 --> 00:33:09.799
<v Speaker 2>gives you maybe up to ten seconds off the main thread,

686
00:33:10.279 --> 00:33:13.400
<v Speaker 2>but you must call finish on the pending result object

687
00:33:13.440 --> 00:33:15.920
<v Speaker 2>returned by go a sink when your background work completes.

688
00:33:16.400 --> 00:33:19.200
<v Speaker 2>It extends the receiver's life slightly, but it's still not

689
00:33:19.240 --> 00:33:20.799
<v Speaker 2>suitable for long running tasks.

690
00:33:20.920 --> 00:33:23.400
<v Speaker 1>Okay, so what about penningintent dot get service? Can't the

691
00:33:23.480 --> 00:33:26.799
<v Speaker 1>alarm just start a service directly to do the long work.

692
00:33:27.000 --> 00:33:29.079
<v Speaker 2>You can do that, but the source points out it's

693
00:33:29.079 --> 00:33:33.079
<v Speaker 2>often unreliable, especially for wake up alarms. Why because starting

694
00:33:33.079 --> 00:33:36.079
<v Speaker 2>a service is a synchronous the alarm might fire. Start

695
00:33:36.119 --> 00:33:38.599
<v Speaker 2>service gets called, but the device might go back to

696
00:33:38.640 --> 00:33:40.839
<v Speaker 2>sleep before the service has fully started and had a

697
00:33:40.920 --> 00:33:42.559
<v Speaker 2>chance to acquire its own wakelock.

698
00:33:42.960 --> 00:33:46.160
<v Speaker 1>Ah, So the service might get started and then immediately

699
00:33:46.559 --> 00:33:47.960
<v Speaker 1>killed as the device sleeps again.

700
00:33:48.119 --> 00:33:52.480
<v Speaker 2>Exactly the work might never actually happen. So for reliable,

701
00:33:52.559 --> 00:33:55.359
<v Speaker 2>long running background work triggered by a wake up alarm,

702
00:33:55.480 --> 00:33:59.200
<v Speaker 2>there's a standard, more robust pattern who alarm manager triggers

703
00:33:59.200 --> 00:34:03.599
<v Speaker 2>a penning intent get broadcast for a broadcast receiver. Because

704
00:34:03.599 --> 00:34:05.799
<v Speaker 2>it's a broadcast triggered by a wake up alarm, the

705
00:34:05.839 --> 00:34:08.239
<v Speaker 2>system guarantees the device is held awake long enough for

706
00:34:08.320 --> 00:34:09.360
<v Speaker 2>on receive to start.

707
00:34:09.519 --> 00:34:10.960
<v Speaker 1>Okay, receiver starts.

708
00:34:11.000 --> 00:34:13.800
<v Speaker 2>Inside on receive. The very first thing the receiver does

709
00:34:13.920 --> 00:34:17.719
<v Speaker 2>is acquire a partial wakelock. This tells the system keep

710
00:34:17.719 --> 00:34:19.559
<v Speaker 2>the CPU running, I have work to do.

711
00:34:19.719 --> 00:34:21.480
<v Speaker 1>Got the lock then what Then?

712
00:34:21.679 --> 00:34:25.039
<v Speaker 2>While holding the lock, the receiver calls start service to

713
00:34:25.119 --> 00:34:28.239
<v Speaker 2>start your actual worker service like an intent service or

714
00:34:28.280 --> 00:34:31.000
<v Speaker 2>a custom service. It typically passes a reference to the

715
00:34:31.000 --> 00:34:34.079
<v Speaker 2>wakelock or just lets the service acquire its own to

716
00:34:34.159 --> 00:34:34.639
<v Speaker 2>the service.

717
00:34:34.760 --> 00:34:37.639
<v Speaker 1>So the receiver's job is just get woken up, grab

718
00:34:37.679 --> 00:34:40.639
<v Speaker 1>the lock, start the service and that's it pretty much.

719
00:34:41.079 --> 00:34:43.920
<v Speaker 2>The service then starts up guaranteed to happen because the

720
00:34:43.920 --> 00:34:48.719
<v Speaker 2>wakelock is held, does its potentially long running work, and critically,

721
00:34:48.920 --> 00:34:51.760
<v Speaker 2>when the work is finished, the service is responsible for

722
00:34:51.880 --> 00:34:53.760
<v Speaker 2>releasing the wekelock that.

723
00:34:53.719 --> 00:34:56.679
<v Speaker 1>Ensures the device stays awake exactly as long as needed

724
00:34:56.679 --> 00:34:58.079
<v Speaker 1>for the work, but no longer.

725
00:34:58.280 --> 00:35:02.199
<v Speaker 2>Precisely, it's a handoff. The source mentions the wakeful broadcast

726
00:35:02.239 --> 00:35:07.000
<v Speaker 2>receiver helper class which simplifies managing this weightlock handoff between

727
00:35:07.039 --> 00:35:08.320
<v Speaker 2>the receiver and the service.

728
00:35:08.400 --> 00:35:10.960
<v Speaker 1>Okay, that makes sense. So alarm manager for future scheduling,

729
00:35:11.079 --> 00:35:15.039
<v Speaker 1>especially across app restarts or device sleep using the broadcast

730
00:35:15.079 --> 00:35:19.880
<v Speaker 1>receiver plus wakelock plus service pattern for reliable, long running

731
00:35:19.920 --> 00:35:20.760
<v Speaker 1>wakeful tasks.

732
00:35:20.920 --> 00:35:22.679
<v Speaker 2>That's a reliable way to do it. Use it for

733
00:35:22.840 --> 00:35:27.639
<v Speaker 2>scheduling periodic sinks, triggering reminders, running maintenance tasks at specific times.

734
00:35:27.679 --> 00:35:30.960
<v Speaker 1>Wow, that's a comprehensive toolkit. So wrapping this up, the

735
00:35:31.000 --> 00:35:35.199
<v Speaker 1>core message from Asynchronous Android seems crystal clear. Keeping that

736
00:35:35.239 --> 00:35:38.199
<v Speaker 1>main UI thread free is paramount for a response of

737
00:35:38.280 --> 00:35:39.800
<v Speaker 1>that you have to offload work.

738
00:35:40.119 --> 00:35:43.760
<v Speaker 2>Absolutely, and we've walked through the spectrum of tools andre it. It

739
00:35:43.599 --> 00:35:46.400
<v Speaker 2>gives you to achieve that each has its place, from

740
00:35:46.440 --> 00:35:50.039
<v Speaker 2>the relatively simple UI focused async task to.

741
00:35:50.360 --> 00:35:54.000
<v Speaker 1>The fundamental building blocks of handler looper and handler thread

742
00:35:54.440 --> 00:35:57.000
<v Speaker 1>for more general purpose thread communication and scheduling.

743
00:35:57.159 --> 00:36:00.960
<v Speaker 2>Then loaders, which are specialized for efficient life cycle aware

744
00:36:01.079 --> 00:36:03.079
<v Speaker 2>data loading into the UI.

745
00:36:03.239 --> 00:36:07.039
<v Speaker 1>Intense service for simple, reliable cue background work.

746
00:36:06.880 --> 00:36:09.360
<v Speaker 2>The more powerful base service for when you need custom

747
00:36:09.400 --> 00:36:13.159
<v Speaker 2>concurrency or more complex communication like binding.

748
00:36:12.960 --> 00:36:16.000
<v Speaker 1>And finally, alarm manager for scheduling tasks well into the

749
00:36:16.039 --> 00:36:19.760
<v Speaker 1>future even when the device is asleep using that wayclock

750
00:36:19.840 --> 00:36:21.119
<v Speaker 1>pattern for reliability.

751
00:36:21.360 --> 00:36:24.320
<v Speaker 2>It really forces you to think about concurrency and resource

752
00:36:24.360 --> 00:36:25.719
<v Speaker 2>management right from the start.

753
00:36:25.920 --> 00:36:28.880
<v Speaker 1>It really does. It highlights how designing for the sometimes

754
00:36:28.880 --> 00:36:32.320
<v Speaker 1>harsh constraints of mobile limited battery, the absolute need for

755
00:36:32.400 --> 00:36:36.960
<v Speaker 1>responsiveness managing life cycles really shapes how you approach software development.

756
00:36:37.239 --> 00:36:39.880
<v Speaker 2>It definitely does, and it leaves us with a final thought,

757
00:36:40.039 --> 00:36:42.159
<v Speaker 2>maybe something for you the listener too them all over,

758
00:36:42.679 --> 00:36:46.679
<v Speaker 2>How does this deep dive into Android's asynchronous patterns, this

759
00:36:46.840 --> 00:36:50.480
<v Speaker 2>necessity of keeping critical threads free and managing resources carefully

760
00:36:50.480 --> 00:36:53.480
<v Speaker 2>on mobile? How does that inform or maybe change, how

761
00:36:53.519 --> 00:36:55.960
<v Speaker 2>you think about write a software, even on platforms with

762
00:36:56.000 --> 00:37:00.000
<v Speaker 2>seemingly abundant resources. Do these principles of responsive no news

763
00:37:00.199 --> 00:37:02.679
<v Speaker 2>and careful concurrency management translate more broadly,
