Видео. Google I/O '17 Architecture Components - Introduction. Перевод субтитров.
Теги: Java, Android, Архитектура, Video, Youtube, Translate, Google I/O '17, Architecture Components, Философия
Перевод английских субтитров на русские из видео Architecture Components - Introduction (Google I/O ‘17). Предпринят только для практики перевода с английского, скажем так to improve my reading and listening skills. Делается постепенно. Начало 20.08.2017, конец - 31.08.2017. All rights reserved.
Смотри другие переводы видео (субтитры) по этой теме: Tag: Architecture Components
Мой клон с русскими субтитрами:
Оригинальное видео:
Аннотация к видео:
- Writing robust Android apps can be challenging, between complex lifecycle issues, unreliable mobile networks, and constrained device capabilities. Mistakes in these areas lead to memory leaks, crashing apps, drained batteries, and unhappy users. This session will cover a new approach to good Android app architecture, including an overview of functionality that will make these problems fundamentally easier to solve. This session is the first of three on this new initiative; be sure to check out the other two “Architecture Components” sessions.
Перевод:
- Написание надежных приложений для Android может оказаться сложной задачей среди нетривиальных проблем регулирования жизненного цикла компонентов, ненадежных мобильных сетей и ограниченной производительности устройств. Ошибки в этих областях приводят к утечкам памяти, падениям приложений, неэффективному расходу батареи и, в итоге, к несчастным пользователям. Эта сессия будет посвящена новому подходу к хорошей архитектуре приложений для Android. В ней представлен обзор функциональности, которая позволит принципиально упростить решение данных проблем. Эта сессия является первой из трёх посвященных архитектурным компонентам. Обязательно посмотрите две другие.
Некоторые ссылки для понимая того, о чем говорится в докладе:
- единая точка входа для архитектурных компонентов - LiveData, ViewModel, LifecycleObserver, LifecycleOwner, Room (абстрация над SQLite базой данных), etc.
- Android Persistence: Room Library - tutorial codelab.
- о Room - article with Kotlin.
- Room, ViewModel, LifeCycle, LiveData - article
- Android lifecycle-aware components - tutorial codelab.
- Architecture Components: Improve Your App’s Design - видео-обзор от Google новых архитектурных компонентов, 5 мин 41 сек на просмотр.
English | Русский |
---|---|
1 00:00:00,000 --> 00:00:05,189 [MUSIC PLAYING] 2 00:00:05,189 --> 00:00:05,980 MIKE CLERON: So hi. 3 00:00:05,980 --> 00:00:07,080 I'm Mike Cleron. 4 00:00:07,080 --> 00:00:08,650 I'm on the Android team. 5 00:00:08,650 --> 00:00:14,120 I manage the system UI framework and UI toolkit teams there. 6 00:00:14,120 --> 00:00:17,650 We're going to be talking today in a lot of detail 7 00:00:17,650 --> 00:00:21,790 about some big changes to how we recommend that you 8 00:00:21,790 --> 00:00:23,710 build Android applications. 9 00:00:23,710 --> 00:00:26,110 But before we go into a lot of the details, 10 00:00:26,110 --> 00:00:28,510 I thought would be helpful to step back a bit, 11 00:00:28,510 --> 00:00:31,960 and frame the discussion by talking about where we came 12 00:00:31,960 --> 00:00:34,730 from, and where we're going. 13 00:00:34,730 --> 00:00:36,100 So let's do that. 14 00:00:36,100 --> 00:00:39,010 So to start, Android has always been based 15 00:00:39,010 --> 00:00:41,230 on some strong principles. 16 00:00:41,230 --> 00:00:43,330 Not surprisingly, those were best expressed 17 00:00:43,330 --> 00:00:44,860 by Dianne Hackborn. 18 00:00:44,860 --> 00:00:46,600 She's the one who actually architected 19 00:00:46,600 --> 00:00:48,880 most of the Android framework. 20 00:00:48,880 --> 00:00:51,160 She wrote a post about this a few months back, 21 00:00:51,160 --> 00:00:54,310 and I have some excerpts from that here. 22 00:00:54,310 --> 00:00:56,230 If you look at our core primitives-- 23 00:00:56,230 --> 00:01:00,100 activity, broadcast receiver, service content provider, 24 00:01:00,100 --> 00:01:03,880 you might reasonably think that those constitute an application 25 00:01:03,880 --> 00:01:05,012 framework. 26 00:01:05,012 --> 00:01:06,970 But that's not the right way to think about it. 27 00:01:06,970 --> 00:01:10,120 These classes are actually contracts 28 00:01:10,120 --> 00:01:14,910 between the application and the operating system. 29 00:01:14,910 --> 00:01:16,950 They represent the minimal amount of information 30 00:01:16,950 --> 00:01:20,790 necessary so that the OS knows what's going on inside your app 31 00:01:20,790 --> 00:01:23,220 so we can manage it properly. 32 00:01:23,220 --> 00:01:27,060 So as an example, if your app is running in the background, 33 00:01:27,060 --> 00:01:29,600 but is also exposing data to another application 34 00:01:29,600 --> 00:01:32,492 through a content provider, the OS needs to know that. 35 00:01:32,492 --> 00:01:34,950 And we need to know that so we don't accidentally kill you. 36 00:01:34,950 --> 00:01:37,500 The content provider is a mechanism that tells us that 37 00:01:37,500 --> 00:01:39,990 so that we can keep you alive. 38 00:01:39,990 --> 00:01:41,970 So we think of these core classes 39 00:01:41,970 --> 00:01:44,790 as really being like the fundamental laws of physics 40 00:01:44,790 --> 00:01:47,520 for Android, hence the illustration. 41 00:01:47,520 --> 00:01:49,920 That is the cover of the manuscript 42 00:01:49,920 --> 00:01:52,170 where Isaac Newton first presented 43 00:01:52,170 --> 00:01:53,430 the basic laws of motion. 44 00:01:53,430 --> 00:01:56,620 45 00:01:56,620 --> 00:01:59,580 Now, fundamental laws are a good thing. 46 00:01:59,580 --> 00:02:01,560 I use a shorthand when talking about this. 47 00:02:01,560 --> 00:02:04,530 I say, Android has good bones, even though people look at me 48 00:02:04,530 --> 00:02:06,780 funny after I say that. 49 00:02:06,780 --> 00:02:09,960 But what I mean by that is that Android 50 00:02:09,960 --> 00:02:13,650 is based on a small, stable, cohesive set 51 00:02:13,650 --> 00:02:15,150 of core primitives. 52 00:02:15,150 --> 00:02:18,390 And that allows a common programming model 53 00:02:18,390 --> 00:02:20,940 across a really incredibly diverse range 54 00:02:20,940 --> 00:02:24,750 of devices from wearables to phones to tablets 55 00:02:24,750 --> 00:02:27,870 to TVs to cars, and more. 56 00:02:27,870 --> 00:02:30,210 This model also gives application developers 57 00:02:30,210 --> 00:02:32,310 the freedom to choose whatever framework 58 00:02:32,310 --> 00:02:34,170 they want inside their application 59 00:02:34,170 --> 00:02:36,010 for their internal framework. 60 00:02:36,010 --> 00:02:38,070 So that means that we on the Android team 61 00:02:38,070 --> 00:02:41,250 don't have to get involved in debates about whether MVC 62 00:02:41,250 --> 00:02:45,540 is better than MVP, or whether MVP is better than [? MVVBM. ?] 63 00:02:45,540 --> 00:02:49,260 You guys can pick whatever makes sense to you. 64 00:02:49,260 --> 00:02:52,680 Now, that's a pretty good story if you are in the operating 65 00:02:52,680 --> 00:02:55,921 system business like, say, me. 66 00:02:55,921 --> 00:02:57,420 But if you're in the app development 67 00:02:57,420 --> 00:03:01,110 business like, say, all of you, that's 68 00:03:01,110 --> 00:03:03,120 really only chapter one of the story. 69 00:03:03,120 --> 00:03:04,890 And the reason for that is because 70 00:03:04,890 --> 00:03:08,190 while strong fundamentals and freedom of choice 71 00:03:08,190 --> 00:03:12,000 are good things, we know that in your day to day jobs-- 72 00:03:12,000 --> 00:03:16,730 and we know this because you told us, you want more from us. 73 00:03:16,730 --> 00:03:19,690 So I'm going to abuse my analogy a bit here. 74 00:03:19,690 --> 00:03:22,810 We can all appreciate the simple elegance of Newton's laws 75 00:03:22,810 --> 00:03:27,725 of motion, but if your job is to land a Rover on Mars, 76 00:03:27,725 --> 00:03:29,350 you don't want to come to work each day 77 00:03:29,350 --> 00:03:31,810 and start with only F equals ma, and derive everything 78 00:03:31,810 --> 00:03:35,230 from first principles. 79 00:03:35,230 --> 00:03:37,780 So we've been talking to developers, both inside 80 00:03:37,780 --> 00:03:41,140 and outside of Google, and taking a hard look at the app 81 00:03:41,140 --> 00:03:42,830 development experience. 82 00:03:42,830 --> 00:03:45,230 And we've realized a couple of things. 83 00:03:45,230 --> 00:03:47,770 First, there are peaks and valleys. 84 00:03:47,770 --> 00:03:51,550 Some aspects of app development are better served by our APIs 85 00:03:51,550 --> 00:03:52,570 than others. 86 00:03:52,570 --> 00:03:56,470 For example, we think RecyclerView is that the better 87 00:03:56,470 --> 00:03:57,830 end of that spectrum. 88 00:03:57,830 --> 00:04:02,020 So with RecyclerView, we didn't say, hey, we give you events, 89 00:04:02,020 --> 00:04:03,810 and you can draw stuff. 90 00:04:03,810 --> 00:04:07,600 And in between you have a Turing complete language, so good luck 91 00:04:07,600 --> 00:04:09,550 with everything else. 92 00:04:09,550 --> 00:04:12,640 On the other hand, maybe Activity 93 00:04:12,640 --> 00:04:16,510 and Fragment Lifecycles belong down in that dark shadowy place 94 00:04:16,510 --> 00:04:18,730 because there, I think, too much of it 95 00:04:18,730 --> 00:04:21,790 is indeed left as an exercise for the reader. 96 00:04:21,790 --> 00:04:24,730 And we want to fix that. 97 00:04:24,730 --> 00:04:27,250 So as we thought about this, we realized the good solution 98 00:04:27,250 --> 00:04:29,930 has key properties. 99 00:04:29,930 --> 00:04:32,194 First, we have to solve the right problems. 100 00:04:32,194 --> 00:04:33,860 This is going to be a sustained effort-- 101 00:04:33,860 --> 00:04:36,320 like sustained for us on Android. 102 00:04:36,320 --> 00:04:38,410 But for the first cut, we want to make sure 103 00:04:38,410 --> 00:04:39,910 that we are going after the problems 104 00:04:39,910 --> 00:04:42,040 that every developer faces, the things that 105 00:04:42,040 --> 00:04:45,040 are hard to do right right now. 106 00:04:45,040 --> 00:04:47,574 Again, app Lifecycles is a really good example. 107 00:04:47,574 --> 00:04:49,240 If you don't get that right in your app, 108 00:04:49,240 --> 00:04:51,236 nothing is going to work on top of that. 109 00:04:51,236 --> 00:04:53,110 And that's true for your app, but that's also 110 00:04:53,110 --> 00:04:55,026 true for the frameworks we're trying to build. 111 00:04:55,026 --> 00:04:58,420 We have to get that right before we can do anything else. 112 00:04:58,420 --> 00:05:00,370 Second, we have to play well with others. 113 00:05:00,370 --> 00:05:02,830 We know that you all have huge investments in your existing 114 00:05:02,830 --> 00:05:05,196 code bases, and we can't create a model 115 00:05:05,196 --> 00:05:06,820 where the first thing we say to you is, 116 00:05:06,820 --> 00:05:08,940 throw all that out and start over. 117 00:05:08,940 --> 00:05:12,070 So we're trying to create APIs that you can adopt a little bit 118 00:05:12,070 --> 00:05:15,580 at a time, and also that interoperate well 119 00:05:15,580 --> 00:05:19,710 with other libraries or other frameworks. 120 00:05:19,710 --> 00:05:22,054 Third, we want to be more opinionated. 121 00:05:22,054 --> 00:05:23,970 We're going to take a stronger, clearer stance 122 00:05:23,970 --> 00:05:26,000 on how to Android and app the right way, 123 00:05:26,000 --> 00:05:27,100 at least as we see it. 124 00:05:27,100 --> 00:05:29,100 Now, this is all still optional. 125 00:05:29,100 --> 00:05:31,330 And if you already have something that works for you, 126 00:05:31,330 --> 00:05:33,030 then great. 127 00:05:33,030 --> 00:05:36,210 But developers are telling us that they want more guidance 128 00:05:36,210 --> 00:05:38,590 on how apps should be built. And by the way, 129 00:05:38,590 --> 00:05:40,770 we're not changing any of the laws of physics here, 130 00:05:40,770 --> 00:05:43,860 we're just layering some higher level constructs on top. 131 00:05:43,860 --> 00:05:46,620 Because after all, F is going to equal ma whether you 132 00:05:46,620 --> 00:05:49,860 believe it should or not. 133 00:05:49,860 --> 00:05:52,140 Next, it needs to scale. 134 00:05:52,140 --> 00:05:54,420 We want solutions that are industrial strength, 135 00:05:54,420 --> 00:05:56,760 and that will scale to the real world requirements 136 00:05:56,760 --> 00:05:58,474 of real world applications. 137 00:05:58,474 --> 00:06:01,140 We don't want to build something that's awesome for Hello World, 138 00:06:01,140 --> 00:06:03,181 but then it's going to collapse the first time it 139 00:06:03,181 --> 00:06:07,620 bumps into the messy complexities of reality. 140 00:06:07,620 --> 00:06:09,410 And finally, reach. 141 00:06:09,410 --> 00:06:11,310 For this problem, for making it easier 142 00:06:11,310 --> 00:06:13,830 for you to write Android applications the right way-- 143 00:06:13,830 --> 00:06:15,690 what we think is the right way, we 144 00:06:15,690 --> 00:06:18,390 want to use libraries like Support Lib wherever possible 145 00:06:18,390 --> 00:06:21,150 rather than adding new APIs to the platform, 146 00:06:21,150 --> 00:06:24,030 because lets our solution reach older versions of the OS 147 00:06:24,030 --> 00:06:26,745 as well. 148 00:06:26,745 --> 00:06:29,370 OK, so that's the background on what we're trying to accomplish 149 00:06:29,370 --> 00:06:30,440 and why we're here. 150 00:06:30,440 --> 00:06:33,309 Now we'd like to introduce Yigit, tool kit engineer 151 00:06:33,309 --> 00:06:35,600 extraordinaire, and he's going to walk you through what 152 00:06:35,600 --> 00:06:36,860 we actually built. Thank you. 153 00:06:36,860 --> 00:06:37,290 [APPLAUSE] 154 00:06:37,290 --> 00:06:38,248 YIGIT BOYAR: All right. 155 00:06:38,248 --> 00:06:39,322 Thanks, Frank. 156 00:06:39,322 --> 00:06:43,610 157 00:06:43,610 --> 00:06:44,410 Hello everybody. 158 00:06:44,410 --> 00:06:46,930 So that was the background. 159 00:06:46,930 --> 00:06:49,050 What are we shipping today? 160 00:06:49,050 --> 00:06:51,210 The very first thing we are shipping 161 00:06:51,210 --> 00:06:55,230 is an architecture guide on developer Android com. 162 00:06:55,230 --> 00:06:58,440 Now for over years, you've been asking us for our opinion. 163 00:06:58,440 --> 00:07:02,220 Like how do we think that an application should be built? 164 00:07:02,220 --> 00:07:03,900 And this is that guide. 165 00:07:03,900 --> 00:07:06,270 So we believe that it's very good, 166 00:07:06,270 --> 00:07:08,730 covers lots of application cases. 167 00:07:08,730 --> 00:07:10,890 But even if you have an architecture 168 00:07:10,890 --> 00:07:14,040 that you are comfortable with, you can keep it. 169 00:07:14,040 --> 00:07:18,300 But you can probably learn something from this guide. 170 00:07:18,300 --> 00:07:20,910 Second, we are shipping a new set of libraries 171 00:07:20,910 --> 00:07:23,290 that we call architecture components. 172 00:07:23,290 --> 00:07:24,900 These are more fundamental components 173 00:07:24,900 --> 00:07:28,440 where you can build your application on top. 174 00:07:28,440 --> 00:07:29,760 The first thing is Lifecycles. 175 00:07:29,760 --> 00:07:33,000 So this is the biggest developer complaint that we have. 176 00:07:33,000 --> 00:07:35,610 Lifecycles are hard, Lifecycles are hard. 177 00:07:35,610 --> 00:07:38,020 And we said, OK, we should solve this problem. 178 00:07:38,020 --> 00:07:41,850 And the first level of this, this new set of components. 179 00:07:41,850 --> 00:07:44,070 Second one is Lifecycle-aware observables, 180 00:07:44,070 --> 00:07:46,860 which will go in detail later, but this is basically 181 00:07:46,860 --> 00:07:51,730 things that can do something based on the Lifecycle. 182 00:07:51,730 --> 00:07:54,810 Third, we are going to introduce a lightweight ViewModel, which 183 00:07:54,810 --> 00:07:58,020 is all of our effort to take out that code 184 00:07:58,020 --> 00:08:00,150 outside of your Activities and Fragments, 185 00:08:00,150 --> 00:08:03,550 and put it somewhere else where you can easily test it. 186 00:08:03,550 --> 00:08:06,630 Last but not least, we are going to introduce a new object 187 00:08:06,630 --> 00:08:10,290 mapping library for SQLite. 188 00:08:10,290 --> 00:08:15,248 And all of this is available for you today on Maven Google com. 189 00:08:15,248 --> 00:08:24,290 [APPLAUSE] 190 00:08:24,290 --> 00:08:25,790 Let's talk about Lifecycles. 191 00:08:25,790 --> 00:08:27,830 So what is what's hard about Lifecycles? 192 00:08:27,830 --> 00:08:29,970 Why do we hear so many complaints about that? 193 00:08:29,970 --> 00:08:31,510 Let's go through an example. 194 00:08:31,510 --> 00:08:33,440 Assume we have an activity where we 195 00:08:33,440 --> 00:08:36,591 want to show the location of the device on the screen. 196 00:08:36,591 --> 00:08:38,090 So you will try something like this. 197 00:08:38,090 --> 00:08:41,280 You create a LocationListener on Create method, 198 00:08:41,280 --> 00:08:43,250 you need to initialize it with the context, 199 00:08:43,250 --> 00:08:46,520 and you have a callback that it calls whenever the location 200 00:08:46,520 --> 00:08:48,800 changes, and you update the UI. 201 00:08:48,800 --> 00:08:51,230 Now, if you have ever written an Android application, 202 00:08:51,230 --> 00:08:54,330 you know that this code is never enough. 203 00:08:54,330 --> 00:08:57,440 You also need to go ahead and override onStart, and then 204 00:08:57,440 --> 00:09:01,880 tell it to start, and override onStop, and tell it to stop. 205 00:09:01,880 --> 00:09:04,040 You always need to do this babysitting 206 00:09:04,040 --> 00:09:05,510 for these components. 207 00:09:05,510 --> 00:09:06,840 But this is acceptable. 208 00:09:06,840 --> 00:09:09,680 This a simple example, this looks all right. 209 00:09:09,680 --> 00:09:11,750 But then your product manager comes and says, 210 00:09:11,750 --> 00:09:12,560 oh, you know what? 211 00:09:12,560 --> 00:09:16,160 We need to first check the user settings before enable-- 212 00:09:16,160 --> 00:09:17,710 asking for a location. 213 00:09:17,710 --> 00:09:22,160 Then your developer says, OK, sure, that's an easy change. 214 00:09:22,160 --> 00:09:25,570 I'm going to change this method to first call this utility 215 00:09:25,570 --> 00:09:27,980 method, which probably makes a web service call 216 00:09:27,980 --> 00:09:29,900 to check the user settings. 217 00:09:29,900 --> 00:09:32,030 And then if the user is enrolled, 218 00:09:32,030 --> 00:09:34,160 then we want to start the LocationListener. 219 00:09:34,160 --> 00:09:37,010 Which looks like a very simple change, 220 00:09:37,010 --> 00:09:39,440 you will think this would work, but let's look 221 00:09:39,440 --> 00:09:42,440 at what happens in that activity's Lifecycle. 222 00:09:42,440 --> 00:09:43,990 So our activity was created. 223 00:09:43,990 --> 00:09:49,526 We said, OK, run start check if the user status is enrolled. 224 00:09:49,526 --> 00:09:52,370 Then meanwhile, user wants to rotate the device. 225 00:09:52,370 --> 00:09:54,930 Which, rotation means a configuration change, 226 00:09:54,930 --> 00:09:58,430 which means Android is going to recreate that activity. 227 00:09:58,430 --> 00:10:00,200 So in onStop, we knew about this, 228 00:10:00,200 --> 00:10:03,292 and we said, OK, location manager stop. 229 00:10:03,292 --> 00:10:05,780 And then the new activity came, it also 230 00:10:05,780 --> 00:10:07,430 goes through the same thing. 231 00:10:07,430 --> 00:10:10,280 Looks all right, except do you remember this call 232 00:10:10,280 --> 00:10:12,140 we made before? 233 00:10:12,140 --> 00:10:15,400 That little change, and then it decides to come back. 234 00:10:15,400 --> 00:10:17,110 Hey, user is enrolled. 235 00:10:17,110 --> 00:10:18,080 And then what we did? 236 00:10:18,080 --> 00:10:20,790 We said, OK, then start. 237 00:10:20,790 --> 00:10:22,250 And you realize the [INAUDIBLE]? 238 00:10:22,250 --> 00:10:26,510 We called start after calling on stop, which means 239 00:10:26,510 --> 00:10:28,700 our activity will live forever. 240 00:10:28,700 --> 00:10:31,130 We are going to observe the location forever, 241 00:10:31,130 --> 00:10:32,257 the battery will drain. 242 00:10:32,257 --> 00:10:33,215 We will have sad users. 243 00:10:33,215 --> 00:10:37,078 244 00:10:37,078 --> 00:10:38,600 This is situation, right? 245 00:10:38,600 --> 00:10:40,220 We want to get rid of this. 246 00:10:40,220 --> 00:10:41,840 We want to put an end to this. 247 00:10:41,840 --> 00:10:43,950 So we said, OK, we need to acknowledge-- 248 00:10:43,950 --> 00:10:46,670 like as Mike mentioned, we cannot change the laws, 249 00:10:46,670 --> 00:10:49,670 but we can make it easier to deal with these things. 250 00:10:49,670 --> 00:10:52,430 So we decided to introduce a new interface called 251 00:10:52,430 --> 00:10:53,970 LifecycleOwner. 252 00:10:53,970 --> 00:10:55,970 This is a thing with a Lifecycle. 253 00:10:55,970 --> 00:10:58,400 Is your activity, is your fragment-- or maybe 254 00:10:58,400 --> 00:11:02,270 you have your own UI framework, whatever the container you have 255 00:11:02,270 --> 00:11:05,570 there as a LifecycleOwner. 256 00:11:05,570 --> 00:11:08,780 And we have these LifecycleObservers, 257 00:11:08,780 --> 00:11:11,180 which are the things that care about the Lifecycle. 258 00:11:11,180 --> 00:11:13,310 Like the LocationListener we had, 259 00:11:13,310 --> 00:11:16,580 it cares about the Lifecycle, it wants to stop itself 260 00:11:16,580 --> 00:11:18,680 if the Lifecycle is not active. 261 00:11:18,680 --> 00:11:21,130 So we said, OK, we will acknowledge this. 262 00:11:21,130 --> 00:11:23,600 And we have a LifecycleObservers. 263 00:11:23,600 --> 00:11:26,090 And we'll go through the code through our activity. 264 00:11:26,090 --> 00:11:30,080 Now we make our activity extend the LifecycleActivity class. 265 00:11:30,080 --> 00:11:33,320 This is just a temporary class until these components 266 00:11:33,320 --> 00:11:34,410 reach 1.0. 267 00:11:34,410 --> 00:11:35,900 Then everything in Support Library 268 00:11:35,900 --> 00:11:39,980 will implement this LifecycleOwner interface. 269 00:11:39,980 --> 00:11:42,550 Inside of our activity, when we initialize 270 00:11:42,550 --> 00:11:45,710 our LocationListener, we are going to tell it, 271 00:11:45,710 --> 00:11:48,240 this is the Lifecycle you care about. 272 00:11:48,240 --> 00:11:50,390 And that's all we will do. 273 00:11:50,390 --> 00:11:54,410 But as it's the same, it calls back the update UI. 274 00:11:54,410 --> 00:11:57,020 So how can we change our LocationListener 275 00:11:57,020 --> 00:12:00,890 to take advantage of this Lifecycle? 276 00:12:00,890 --> 00:12:03,500 Oh, we do the same thing for the UserStatus as well. 277 00:12:03,500 --> 00:12:06,240 278 00:12:06,240 --> 00:12:08,880 So there's some boilerplate code here to get the fields. 279 00:12:08,880 --> 00:12:10,950 It doesn't really matter, but we have 280 00:12:10,950 --> 00:12:14,850 this enabled method which gets called if the user is enrolled. 281 00:12:14,850 --> 00:12:16,500 Inside this enabled method, now we 282 00:12:16,500 --> 00:12:18,420 want to start listening to location 283 00:12:18,420 --> 00:12:21,360 only if the activity is started. 284 00:12:21,360 --> 00:12:23,040 Now you can do this. 285 00:12:23,040 --> 00:12:26,590 You can say, what is my current state, which is amazing. 286 00:12:26,590 --> 00:12:29,370 We didn't have this API until now. 287 00:12:29,370 --> 00:12:32,010 Well now you can. 288 00:12:32,010 --> 00:12:34,110 So OK, that was a simple change. 289 00:12:34,110 --> 00:12:36,510 But we also get notified, what if we get 290 00:12:36,510 --> 00:12:38,710 enrolled when the activity was in back state, 291 00:12:38,710 --> 00:12:40,800 and user comes back to the activity. 292 00:12:40,800 --> 00:12:43,290 Now we should actually start the LocationManager. 293 00:12:43,290 --> 00:12:46,290 For this, we want to observe that Lifecycle. 294 00:12:46,290 --> 00:12:48,690 To do that, we implement this interface, 295 00:12:48,690 --> 00:12:50,670 which allows us to write these methods. 296 00:12:50,670 --> 00:12:52,710 You can annotate the methods saying 297 00:12:52,710 --> 00:12:56,152 that, if ON_START happens, call this method. 298 00:12:56,152 --> 00:12:58,360 And the new components will take care of calling you. 299 00:12:58,360 --> 00:13:00,660 So if you are already enabled, now you 300 00:13:00,660 --> 00:13:03,540 start, and ON_STOP you disconnect. 301 00:13:03,540 --> 00:13:06,700 And last but not least, if the activity is destroyed 302 00:13:06,700 --> 00:13:09,220 there is nothing you want to do with that activity 303 00:13:09,220 --> 00:13:11,796 so you can unregister. 304 00:13:11,796 --> 00:13:13,920 So now you might be asking yourself, well, you just 305 00:13:13,920 --> 00:13:16,710 moved those ON_START, ON_STOP methods from the activity 306 00:13:16,710 --> 00:13:18,450 into this Location Manager. 307 00:13:18,450 --> 00:13:20,150 How come it is simpler? 308 00:13:20,150 --> 00:13:22,250 It's simpler because those methods 309 00:13:22,250 --> 00:13:23,610 live in the right place. 310 00:13:23,610 --> 00:13:27,690 It's the Location Manager which cares about the Lifecycle. 311 00:13:27,690 --> 00:13:30,780 So it should be able to do it without the activity 312 00:13:30,780 --> 00:13:32,460 babysitting itself. 313 00:13:32,460 --> 00:13:34,170 I'm sure if you look at your code today, 314 00:13:34,170 --> 00:13:37,260 your activity ON_START, ON_STOP methods are like, at least 20, 315 00:13:37,260 --> 00:13:38,730 30 lines of code. 316 00:13:38,730 --> 00:13:42,060 We want them to be zero lines of code. 317 00:13:42,060 --> 00:13:43,800 If we go back to activity, I want 318 00:13:43,800 --> 00:13:45,780 to point out something that-- 319 00:13:45,780 --> 00:13:49,260 look, in onCreate, we initialized these components. 320 00:13:49,260 --> 00:13:50,580 And that's all we did. 321 00:13:50,580 --> 00:13:53,230 We didn't override, we didn't ON_STOP, ON_START, 322 00:13:53,230 --> 00:13:55,020 we don't override any of those things 323 00:13:55,020 --> 00:13:59,630 because the Location Manager is a Lifecycle aware component 324 00:13:59,630 --> 00:14:01,875 now. 325 00:14:01,875 --> 00:14:03,990 So it's a new concept we want to introduce. 326 00:14:03,990 --> 00:14:08,130 A Lifecycle aware component in a component can get a Lifecycle, 327 00:14:08,130 --> 00:14:09,170 and do the right things. 328 00:14:09,170 --> 00:14:12,210 It can take care of itself so that your activity, 329 00:14:12,210 --> 00:14:15,120 you can just initialize it and forget about it. 330 00:14:15,120 --> 00:14:19,060 You know that's not going to leak you. 331 00:14:19,060 --> 00:14:22,480 Now, of course, it was like more of moving the complex 332 00:14:22,480 --> 00:14:24,520 from activity to the Location Manager, 333 00:14:24,520 --> 00:14:27,310 and then it still needs to deal with Lifecycle. 334 00:14:27,310 --> 00:14:29,190 We said, OK, what do we want? 335 00:14:29,190 --> 00:14:32,540 It's nice to be able to do that, but we want more. 336 00:14:32,540 --> 00:14:35,230 We want a very convenient to handle this common case. 337 00:14:35,230 --> 00:14:38,390 It's very common that your activity or fragment, it 338 00:14:38,390 --> 00:14:41,830 observes some data, and whenever that data changes, 339 00:14:41,830 --> 00:14:43,300 it wants to refresh itself. 340 00:14:43,300 --> 00:14:46,910 It happens basically almost every single UI. 341 00:14:46,910 --> 00:14:49,870 And we want to share resources across multiple fragments 342 00:14:49,870 --> 00:14:51,250 or activities. 343 00:14:51,250 --> 00:14:54,580 The location of the device is the same from fragment 344 00:14:54,580 --> 00:14:55,240 to fragment. 345 00:14:55,240 --> 00:14:57,040 If you have two fragments, why do you 346 00:14:57,040 --> 00:15:01,610 need to create two listeners to listen to the same location? 347 00:15:01,610 --> 00:15:05,080 Hence, we created this new LiveData clause. 348 00:15:05,080 --> 00:15:06,600 Let's look at that. 349 00:15:06,600 --> 00:15:10,390 So LiveData is a data holder, it just holds some data. 350 00:15:10,390 --> 00:15:13,690 It's like an observable, but the tricky thing about LiveData 351 00:15:13,690 --> 00:15:15,760 is that it is Lifecycle aware. 352 00:15:15,760 --> 00:15:18,310 It understands about Lifecycles. 353 00:15:18,310 --> 00:15:20,820 Because it understands about Lifecycles, 354 00:15:20,820 --> 00:15:22,850 it automatically manages subscriptions. 355 00:15:22,850 --> 00:15:25,220 So very similar to the previous example, 356 00:15:25,220 --> 00:15:29,290 if you are observing a LiveData, you don't need to unsubscribe, 357 00:15:29,290 --> 00:15:33,040 the right things will happen in the right times. 358 00:15:33,040 --> 00:15:37,660 So if that LocationListener was a LiveData, and a singleton 359 00:15:37,660 --> 00:15:40,000 because location is singleton, we 360 00:15:40,000 --> 00:15:41,800 could write the code like this-- 361 00:15:41,800 --> 00:15:43,930 get distance, start observing. 362 00:15:43,930 --> 00:15:47,280 And when you observe, you say, this is my Lifecycle. 363 00:15:47,280 --> 00:15:48,280 This all you need to do. 364 00:15:48,280 --> 00:15:51,880 Before on Android, if you were observing something singleton 365 00:15:51,880 --> 00:15:55,180 from an activity, everyone will give minus two 366 00:15:55,180 --> 00:15:56,650 to that code review. 367 00:15:56,650 --> 00:15:57,805 Now you can do this. 368 00:15:57,805 --> 00:16:01,600 This is safe, nothing ever leaks. 369 00:16:01,600 --> 00:16:03,790 So if you want to change your LocationListener 370 00:16:03,790 --> 00:16:07,430 to use this new API, we get rid of the unnecessary things. 371 00:16:07,430 --> 00:16:09,590 All we need is a context to connect. 372 00:16:09,590 --> 00:16:15,540 What we say, this is a LiveData, this a LiveData of a location. 373 00:16:15,540 --> 00:16:18,110 And we get these two new methods. 374 00:16:18,110 --> 00:16:20,520 One of two says onActive, which means 375 00:16:20,520 --> 00:16:22,920 you have an active observer. 376 00:16:22,920 --> 00:16:24,475 And the other one says onInactive, 377 00:16:24,475 --> 00:16:27,555 which means you don't have any observers that are active. 378 00:16:27,555 --> 00:16:30,360 Now at this point, you're probably asking yourself, 379 00:16:30,360 --> 00:16:32,590 what is an active observer? 380 00:16:32,590 --> 00:16:34,290 Well, we define an active observer 381 00:16:34,290 --> 00:16:37,710 as an observer that's in the STARTED or RESUMED state, which 382 00:16:37,710 --> 00:16:40,440 is like an activity user is currently seeing. 383 00:16:40,440 --> 00:16:43,020 So if you have an observer in the back stack, 384 00:16:43,020 --> 00:16:45,300 there's no reason to put this inactive. 385 00:16:45,300 --> 00:16:47,190 There's no reason to update that activity 386 00:16:47,190 --> 00:16:49,950 because user will never, ever see what's going on there. 387 00:16:49,950 --> 00:16:53,390 388 00:16:53,390 --> 00:16:56,130 So inside our connect method, all we need to do 389 00:16:56,130 --> 00:16:58,540 is, whenever the system Location Manager sends us 390 00:16:58,540 --> 00:17:02,120 a new location, we call setValue on ourselves. 391 00:17:02,120 --> 00:17:05,589 Then the LiveData knows which are the active observers, 392 00:17:05,589 --> 00:17:08,410 and delivers the data to those observers. 393 00:17:08,410 --> 00:17:11,930 Or if one of the observers was on the back stack 394 00:17:11,930 --> 00:17:14,290 and then becomes visible again, LiveData 395 00:17:14,290 --> 00:17:17,079 takes care of sending the latest data back to that observer. 396 00:17:17,079 --> 00:17:19,608 397 00:17:19,608 --> 00:17:22,858 And then we can make our LocationListener singleton 398 00:17:22,858 --> 00:17:26,019 because well, we don't need multiple instances. 399 00:17:26,020 --> 00:17:30,400 So if we look at LiveData, it is a Lifecycle aware Observable. 400 00:17:30,400 --> 00:17:32,520 It is very simple start and stop semantics. 401 00:17:32,520 --> 00:17:34,650 Doesn't matter how many observers you have, 402 00:17:34,650 --> 00:17:39,740 or what state they are, we merge all of it into one Lifecycle. 403 00:17:39,740 --> 00:17:42,000 And it doesn't have any activities or fragments 404 00:17:42,000 --> 00:17:44,620 inside it, but it works with both of them. 405 00:17:44,620 --> 00:17:47,460 And is also really used to test LiveData because it's 406 00:17:47,460 --> 00:17:49,080 kind of Android free. 407 00:17:49,080 --> 00:17:52,720 And if you know about this infamous FragmentTransaction 408 00:17:52,720 --> 00:17:56,670 exception, we guarantee that your observer will never, 409 00:17:56,670 --> 00:17:59,750 ever be called in a state where you cannot run 410 00:17:59,750 --> 00:18:01,260 a FragmentTransaction. 411 00:18:01,260 --> 00:18:03,780 So this is very, very specifically designed 412 00:18:03,780 --> 00:18:08,100 to work well with your Activities and Fragments. 413 00:18:08,100 --> 00:18:11,520 OK, let's think about configuration changes. 414 00:18:11,520 --> 00:18:14,460 Now, that example was easy because location is global, 415 00:18:14,460 --> 00:18:17,550 but most of the time, the data belongs to a UI. 416 00:18:17,550 --> 00:18:22,770 So if we had an activity where we show a user profile, 417 00:18:22,770 --> 00:18:24,660 and we implemented a web service that 418 00:18:24,660 --> 00:18:28,260 can return the data as a LiveData which we can safely 419 00:18:28,260 --> 00:18:32,580 observe without risking leaking overactivity, 420 00:18:32,580 --> 00:18:33,470 this all looks nice. 421 00:18:33,470 --> 00:18:35,030 You will never leak this activity, 422 00:18:35,030 --> 00:18:36,390 it will work very well. 423 00:18:36,390 --> 00:18:40,340 Except, what happens if the user rotates to the device? 424 00:18:40,340 --> 00:18:42,850 Let's look at the LifeCycle graph again. 425 00:18:42,850 --> 00:18:44,790 So activity is created, it saves, OK. 426 00:18:44,790 --> 00:18:46,752 Fetch the user. 427 00:18:46,752 --> 00:18:48,460 And then while you are fetching the user, 428 00:18:48,460 --> 00:18:51,390 user decides, oh, I want to rotate the phone. 429 00:18:51,390 --> 00:18:53,130 And then that activity is destroyed. 430 00:18:53,130 --> 00:18:55,740 Luckily we don't leak it, which is great. 431 00:18:55,740 --> 00:18:57,810 But then the new activity starts, 432 00:18:57,810 --> 00:18:59,620 which makes this new call. 433 00:18:59,620 --> 00:19:02,160 Now, this is OK, but not great. 434 00:19:02,160 --> 00:19:03,640 What do we want? 435 00:19:03,640 --> 00:19:05,700 We want to actually retain that data, right? 436 00:19:05,700 --> 00:19:09,870 We are already making that request, why remake it? 437 00:19:09,870 --> 00:19:12,780 So we want our graph to look like this. 438 00:19:12,780 --> 00:19:14,640 So if the new activity comes, we should 439 00:19:14,640 --> 00:19:18,330 be able to give it back the same view model, which is 440 00:19:18,330 --> 00:19:20,340 a new class called ViewModel. 441 00:19:20,340 --> 00:19:22,290 So we are introducing this new class 442 00:19:22,290 --> 00:19:23,760 very specific to this thing, where 443 00:19:23,760 --> 00:19:27,210 you should put the data inside your activities 444 00:19:27,210 --> 00:19:30,940 into the ViewModel, and make the activities data-free. 445 00:19:30,940 --> 00:19:33,000 So if you want to change this activity, 446 00:19:33,000 --> 00:19:36,910 we create this new class, it extends the VewModel class. 447 00:19:36,910 --> 00:19:41,830 Whatever data we had inside the activity, we move it there. 448 00:19:41,830 --> 00:19:45,630 And in the ViewModel, all we do is, inside the getUser method, 449 00:19:45,630 --> 00:19:48,790 if this is the first goal, get it from the web service. 450 00:19:48,790 --> 00:19:51,800 Otherwise, return to existing value. 451 00:19:51,800 --> 00:19:53,220 Now, super simple. 452 00:19:53,220 --> 00:19:55,800 And inside our activity, we get rid of all that code. 453 00:19:55,800 --> 00:19:58,590 We say, get the ViewModelProviders.of this. 454 00:19:58,590 --> 00:20:01,620 So each activity or a fragment has a ViewModelProvider 455 00:20:01,620 --> 00:20:04,680 that you can obtain, and that ViewModelProvider knows 456 00:20:04,680 --> 00:20:06,510 how to give you the ViewModel. 457 00:20:06,510 --> 00:20:08,880 So when you call get MyViewModel, 458 00:20:08,880 --> 00:20:10,530 the very first time you make this call, 459 00:20:10,530 --> 00:20:11,940 we will give you a new instance. 460 00:20:11,940 --> 00:20:13,780 When the rotated activity comes back, 461 00:20:13,780 --> 00:20:16,760 it's going to reconnect to the same ViewModel. 462 00:20:16,760 --> 00:20:19,432 And then the rest of the code is the same. 463 00:20:19,432 --> 00:20:22,318 [APPLAUSE] 464 00:20:22,318 --> 00:20:28,580 465 00:20:28,580 --> 00:20:31,060 So if you look at the Lifecycle, this is how it looks. 466 00:20:31,060 --> 00:20:32,040 This is what we wanted. 467 00:20:32,040 --> 00:20:35,800 The new activity is started, it reconnects. 468 00:20:35,800 --> 00:20:38,140 And when the new activity is finished, 469 00:20:38,140 --> 00:20:41,050 like when we don't have anything to do with that activity, 470 00:20:41,050 --> 00:20:42,580 and then we go and tell ViewModel 471 00:20:42,580 --> 00:20:44,350 that it's not needed anymore. 472 00:20:44,350 --> 00:20:48,340 This is actually the only method in the ViewModel class. 473 00:20:48,340 --> 00:20:49,570 So this is very simple. 474 00:20:49,570 --> 00:20:51,640 So if we look at Lifecycles, they 475 00:20:51,640 --> 00:20:53,310 hold the data for the activity. 476 00:20:53,310 --> 00:20:56,500 They survive configuration changes. 477 00:20:56,500 --> 00:20:58,930 They should never, ever reference views 478 00:20:58,930 --> 00:21:00,870 because they [INAUDIBLE] leave the activities. 479 00:21:00,870 --> 00:21:03,430 So you cannot reference back to the activity. 480 00:21:03,430 --> 00:21:05,640 That's why you use things like LiveData, 481 00:21:05,640 --> 00:21:08,550 Rx Java, or datamining observables 482 00:21:08,550 --> 00:21:10,270 to do that communication. 483 00:21:10,270 --> 00:21:12,730 And this is what our activity talks-- it always 484 00:21:12,730 --> 00:21:15,070 talks to the ViewModel. 485 00:21:15,070 --> 00:21:19,210 Now, another big topic is persistence. 486 00:21:19,210 --> 00:21:22,000 Now, we know that to write a good, responsive Android app, 487 00:21:22,000 --> 00:21:24,860 you need to save the data on disk. 488 00:21:24,860 --> 00:21:27,700 If you come to Android, there's this three major APIs we have. 489 00:21:27,700 --> 00:21:29,980 One of them is content providers, which 490 00:21:29,980 --> 00:21:32,320 is to talk between processes. 491 00:21:32,320 --> 00:21:35,530 It really has nothing to do with persistence, in reality. 492 00:21:35,530 --> 00:21:37,510 The other one is shared preferences, 493 00:21:37,510 --> 00:21:40,090 which saves the data in XML. 494 00:21:40,090 --> 00:21:43,190 So you can only put very little data into that. 495 00:21:43,190 --> 00:21:44,800 And the last one is SQLite, which 496 00:21:44,800 --> 00:21:48,160 is something we have been shipping since Android 1. 497 00:21:48,160 --> 00:21:49,720 So you know you need to use SQLite 498 00:21:49,720 --> 00:21:51,890 if you want to save big data. 499 00:21:51,890 --> 00:21:55,330 And so you go into the developer.android.com/ This is 500 00:21:55,330 --> 00:21:57,960 the very first saving your data slide. 501 00:21:57,960 --> 00:22:00,130 This is so confusing. 502 00:22:00,130 --> 00:22:01,642 This is very sad. 503 00:22:01,642 --> 00:22:03,370 [LAUGHTER] 504 00:22:03,370 --> 00:22:06,190 So is it-- OK, we want to make this less sad. 505 00:22:06,190 --> 00:22:07,960 We want to make it happy. 506 00:22:07,960 --> 00:22:10,060 So we'll look at the example, right? 507 00:22:10,060 --> 00:22:11,740 So there's-- on top, it tries to say, 508 00:22:11,740 --> 00:22:15,670 I want to select these three columns with this constraint, 509 00:22:15,670 --> 00:22:17,950 and I want to order them like this. 510 00:22:17,950 --> 00:22:20,670 This actually really, really simple SQL query, 511 00:22:20,670 --> 00:22:22,210 but you need to write all this code. 512 00:22:22,210 --> 00:22:24,160 Plus, this code doesn't even show where 513 00:22:24,160 --> 00:22:27,720 you define all those constants. 514 00:22:27,720 --> 00:22:29,430 So what do we really want? 515 00:22:29,430 --> 00:22:32,060 We want to get rid of that boilerplate-free code. 516 00:22:32,060 --> 00:22:34,890 When you are writing Java, if you make a typo in Java, 517 00:22:34,890 --> 00:22:36,630 it doesn't compile right. 518 00:22:36,630 --> 00:22:39,010 We want the same thing for SQL. 519 00:22:39,010 --> 00:22:42,000 We still want to use SQLite, because on every single Android 520 00:22:42,000 --> 00:22:43,740 device it's a proven technology. 521 00:22:43,740 --> 00:22:46,230 We know it works very well. 522 00:22:46,230 --> 00:22:48,280 But we want the compile time verification. 523 00:22:48,280 --> 00:22:49,970 So we don't want the boilerplate code, 524 00:22:49,970 --> 00:22:52,480 we want to compile time verification. 525 00:22:52,480 --> 00:22:56,220 So we said, well-- we came up with Room, which is an object 526 00:22:56,220 --> 00:22:59,649 mapping library for SQLite. 527 00:22:59,649 --> 00:23:05,800 [APPLAUSE] 528 00:23:05,800 --> 00:23:08,210 So if you look at this query, we said, 529 00:23:08,210 --> 00:23:10,770 OK, let's move this query inside the annotation. 530 00:23:10,770 --> 00:23:12,610 We like annotations. 531 00:23:12,610 --> 00:23:14,560 And we have this feed object, which we 532 00:23:14,560 --> 00:23:16,360 want to save in the database. 533 00:23:16,360 --> 00:23:19,270 I want to put that query inside an interface. 534 00:23:19,270 --> 00:23:21,280 You want to create the FeedDao-- 535 00:23:21,280 --> 00:23:24,040 the Dao stands for Data Access Object. 536 00:23:24,040 --> 00:23:27,430 Usually in database, the best practice to put your database 537 00:23:27,430 --> 00:23:29,350 access into certain interfaces. 538 00:23:29,350 --> 00:23:32,252 Then we just need to tell the Room, this is a Dow. 539 00:23:32,252 --> 00:23:34,360 Tell Room this is an entity. 540 00:23:34,360 --> 00:23:37,960 And finally, we had a database class which says, 541 00:23:37,960 --> 00:23:41,050 I have these entities-- so you have multiple entities, 542 00:23:41,050 --> 00:23:45,240 and I have these data access objects, as you saw them. 543 00:23:45,240 --> 00:23:46,210 This is all you write. 544 00:23:46,210 --> 00:23:48,760 Once you write that, you can get an implementation of it 545 00:23:48,760 --> 00:23:49,590 from Room. 546 00:23:49,590 --> 00:23:52,750 It's very similar to how you use Retrofit or Dagger-- 547 00:23:52,750 --> 00:23:57,080 you define the interfaces, we provide the implementation. 548 00:23:57,080 --> 00:23:59,740 Now, once we know this is a Dow, we 549 00:23:59,740 --> 00:24:01,210 can do these shortcut methods. 550 00:24:01,210 --> 00:24:05,350 Like, insert these items, or delete these items, or update-- 551 00:24:05,350 --> 00:24:06,930 a bunch of shortcut methods. 552 00:24:06,930 --> 00:24:08,710 And you can press multiple parameters. 553 00:24:08,710 --> 00:24:11,115 As long as you can read it and it makes sense, 554 00:24:11,115 --> 00:24:13,930 Room will understand it. 555 00:24:13,930 --> 00:24:16,000 But the most important part of Room 556 00:24:16,000 --> 00:24:18,680 is, it understands your SQL. 557 00:24:18,680 --> 00:24:20,320 So the part-- all those constants 558 00:24:20,320 --> 00:24:23,630 I mentioned we defined to get compile time guarantees, 559 00:24:23,630 --> 00:24:26,560 Room actually gives all of this for free. 560 00:24:26,560 --> 00:24:28,380 So when Room sees this query, says, 561 00:24:28,380 --> 00:24:31,060 OK, you are receiving these three columns 562 00:24:31,060 --> 00:24:34,900 from this table where the title looks like this keyword. 563 00:24:34,900 --> 00:24:36,705 Where is this keyword coming from? 564 00:24:36,705 --> 00:24:38,710 Oh, it's coming from the function parameters. 565 00:24:38,710 --> 00:24:39,567 Makes sense. 566 00:24:39,567 --> 00:24:40,900 And what does it want to return? 567 00:24:40,900 --> 00:24:42,970 It wants to return a list of feeds. 568 00:24:42,970 --> 00:24:45,330 And then Room goes and checks. 569 00:24:45,330 --> 00:24:47,980 Does the columns returned match the object 570 00:24:47,980 --> 00:24:49,690 the user wants to return? 571 00:24:49,690 --> 00:24:53,812 And once they're equal, it says, OK, I can generate this code. 572 00:24:53,812 --> 00:24:55,270 You can have even say, select star. 573 00:24:55,270 --> 00:24:56,600 You don't need to list them. 574 00:24:56,600 --> 00:25:00,190 Room really, really understand your query. 575 00:25:00,190 --> 00:25:03,130 You can even join 10 tables, it will still work. 576 00:25:03,130 --> 00:25:05,020 But what if you made a typo? 577 00:25:05,020 --> 00:25:07,750 Instead of saying feed table you wrote feeds. 578 00:25:07,750 --> 00:25:10,750 Now, if this happens, Room is going to give you 579 00:25:10,750 --> 00:25:12,940 an error at compile time. 580 00:25:12,940 --> 00:25:15,040 So it goes out and verifies your query 581 00:25:15,040 --> 00:25:17,080 against the schema you have defined, 582 00:25:17,080 --> 00:25:19,562 and it tells you if something is wrong. 583 00:25:19,562 --> 00:25:22,508 [APPLAUSE] 584 00:25:22,508 --> 00:25:27,797 585 00:25:27,797 --> 00:25:29,380 But that's not the only thing it does. 586 00:25:29,380 --> 00:25:30,860 So if you said-- 587 00:25:30,860 --> 00:25:34,070 if your query is correct, you want to fetch ID and title. 588 00:25:34,070 --> 00:25:35,870 This said, well, it's query, but you 589 00:25:35,870 --> 00:25:37,350 want to return it as a string. 590 00:25:37,350 --> 00:25:40,460 And then Room says, well, you are returning two columns, 591 00:25:40,460 --> 00:25:42,260 but you only have one string. 592 00:25:42,260 --> 00:25:43,320 That doesn't make sense. 593 00:25:43,320 --> 00:25:46,800 And it's going to give you a compile time error again. 594 00:25:46,800 --> 00:25:49,220 And there's a really nice way to fix this in Room. 595 00:25:49,220 --> 00:25:51,095 You can basically create any Java class. 596 00:25:51,095 --> 00:25:52,580 It doesn't need to be annotating, 597 00:25:52,580 --> 00:25:55,170 there's nothing special about that Pojo, 598 00:25:55,170 --> 00:25:57,080 and tell Room to return it. 599 00:25:57,080 --> 00:25:59,780 As long as whatever query it returns 600 00:25:59,780 --> 00:26:01,880 matches what you want it to return, 601 00:26:01,880 --> 00:26:05,250 Room will write the code for you. 602 00:26:05,250 --> 00:26:07,470 And observability, which is very important, right? 603 00:26:07,470 --> 00:26:09,390 If you have a query like this, now you're 604 00:26:09,390 --> 00:26:11,460 showing lists of feeds, you obviously 605 00:26:11,460 --> 00:26:14,295 want to get notified when the data changes. 606 00:26:14,295 --> 00:26:17,842 And in Room, if you want to do this, all you have to do 607 00:26:17,842 --> 00:26:19,290 is tell it. 608 00:26:19,290 --> 00:26:22,980 Tell it to return a LiveData, and it will do it for you. 609 00:26:22,980 --> 00:26:26,400 Because it knows your query, it knows what things affect it. 610 00:26:26,400 --> 00:26:29,520 So it can let you know if that query changes. 611 00:26:29,520 --> 00:26:32,280 And this is the part where all these architectural components 612 00:26:32,280 --> 00:26:33,750 work well together. 613 00:26:33,750 --> 00:26:36,640 Room already knows about LiveData. 614 00:26:36,640 --> 00:26:40,340 So your ViewModel, all you would write is-- from the data is, 615 00:26:40,340 --> 00:26:42,600 call this query, and this all it will do. 616 00:26:42,600 --> 00:26:46,650 Whenever that data changes, your UI will get a new update. 617 00:26:46,650 --> 00:26:49,470 And it only happens if the UI is visible. 618 00:26:49,470 --> 00:26:52,958 Last but not least, Room also supports RxJava 2. 619 00:26:52,958 --> 00:26:55,448 [APPLAUSE] 620 00:26:55,448 --> 00:27:01,930 621 00:27:01,930 --> 00:27:04,390 OK, if we look at Room in a nutshell, 622 00:27:04,390 --> 00:27:06,730 it writes the boilerplate code for you. 623 00:27:06,730 --> 00:27:08,050 It has full SQLite support. 624 00:27:08,050 --> 00:27:10,990 You can just write in SQLite, there's no builders. 625 00:27:10,990 --> 00:27:14,070 It verifies your queries at compile time. 626 00:27:14,070 --> 00:27:17,350 It incentivizes best practices, which helps you 627 00:27:17,350 --> 00:27:19,480 with testing migrations. 628 00:27:19,480 --> 00:27:23,020 And it's also observable out of the box. 629 00:27:23,020 --> 00:27:28,000 OK, architecture, our last topic today. 630 00:27:28,000 --> 00:27:30,000 So where we started, right? 631 00:27:30,000 --> 00:27:31,860 And now, you might be asking yourselves, 632 00:27:31,860 --> 00:27:34,335 what has changed in 2017 that you 633 00:27:34,335 --> 00:27:36,930 are talking about architecture? 634 00:27:36,930 --> 00:27:38,740 Well, actually nothing has changed. 635 00:27:38,740 --> 00:27:40,560 We've been talking about this topic a lot. 636 00:27:40,560 --> 00:27:44,460 Adam Powell and I gave a lot of talks on this topic. 637 00:27:44,460 --> 00:27:49,050 There's even a talk from 2010 which I watch as a developer. 638 00:27:49,050 --> 00:27:51,630 So this is a topic we have been more clear about. 639 00:27:51,630 --> 00:27:54,720 But what is missing was a well-defined reference 640 00:27:54,720 --> 00:27:56,022 architecture. 641 00:27:56,022 --> 00:27:57,480 So it's what we are shipping today. 642 00:27:57,480 --> 00:27:59,370 If you go to developer.android.com today 643 00:27:59,370 --> 00:28:01,680 after the session, there's a section 644 00:28:01,680 --> 00:28:05,246 about how to architect an Android application. 645 00:28:05,246 --> 00:28:08,697 [APPLAUSE] 646 00:28:08,697 --> 00:28:13,640 647 00:28:13,640 --> 00:28:15,890 So by the way, this is a reference guide. 648 00:28:15,890 --> 00:28:17,780 This is not your religious book. 649 00:28:17,780 --> 00:28:20,600 We believe this is a very good way to write applications, 650 00:28:20,600 --> 00:28:24,320 but you don't need to follow it line by line. 651 00:28:24,320 --> 00:28:27,400 So I'm going to briefly go through this architecture, 652 00:28:27,400 --> 00:28:28,960 but if you get lost, don't worry. 653 00:28:28,960 --> 00:28:31,950 We have all of this documented on developer Android com 654 00:28:31,950 --> 00:28:34,264 with sample applications. 655 00:28:34,264 --> 00:28:35,680 So we think that an application is 656 00:28:35,680 --> 00:28:37,300 composed of four main things-- 657 00:28:37,300 --> 00:28:41,680 there's UI controllers, the view models, a repository, 658 00:28:41,680 --> 00:28:43,030 and the data sources. 659 00:28:43,030 --> 00:28:45,640 So let's look at these in detail. 660 00:28:45,640 --> 00:28:47,980 UI controllers are your activities, 661 00:28:47,980 --> 00:28:51,100 fragments, custom views. 662 00:28:51,100 --> 00:28:52,750 They have really simple tasks. 663 00:28:52,750 --> 00:28:55,270 They observe the fields of the ViewModel 664 00:28:55,270 --> 00:28:56,720 and update themselves. 665 00:28:56,720 --> 00:28:58,540 And they want more responsibility. 666 00:28:58,540 --> 00:29:01,540 Whenever user takes an action on the UI, 667 00:29:01,540 --> 00:29:04,450 they understand that action, and call the ViewModel 668 00:29:04,450 --> 00:29:07,540 to express whatever the user wanted to do. 669 00:29:07,540 --> 00:29:10,390 If you go to our view model, view model 670 00:29:10,390 --> 00:29:13,450 is the one which prepares the data for the UI, 671 00:29:13,450 --> 00:29:14,480 and holds onto it. 672 00:29:14,480 --> 00:29:16,740 This is where the data for the UI lives. 673 00:29:16,740 --> 00:29:20,050 View model knows how to get that data. 674 00:29:20,050 --> 00:29:21,949 Usually it has LiveData. 675 00:29:21,949 --> 00:29:23,740 If you are using Rx Java, it is observable, 676 00:29:23,740 --> 00:29:26,940 or datamining observables. 677 00:29:26,940 --> 00:29:28,830 It survives configuration changes. 678 00:29:28,830 --> 00:29:32,200 That's why we put the data into the view models. 679 00:29:32,200 --> 00:29:33,680 And it is also the gateway. 680 00:29:33,680 --> 00:29:37,040 You can also consider it as, your UI controller only 681 00:29:37,040 --> 00:29:39,230 ever talks to the view model to reach 682 00:29:39,230 --> 00:29:42,690 to the rest of the application. 683 00:29:42,690 --> 00:29:44,360 And then what's the repository? 684 00:29:44,360 --> 00:29:47,100 Now, the view model serves as a data store 685 00:29:47,100 --> 00:29:48,920 for your UI controller, right? 686 00:29:48,920 --> 00:29:51,060 Repository saves it as a data store 687 00:29:51,060 --> 00:29:53,520 for all of your application. 688 00:29:53,520 --> 00:29:56,070 So it's the complete data model for the app, 689 00:29:56,070 --> 00:29:58,560 and it provides this data with simple APIs 690 00:29:58,560 --> 00:30:00,210 to the rest of the application. 691 00:30:00,210 --> 00:30:03,420 You can have a user repository where you pass a user ID, 692 00:30:03,420 --> 00:30:06,000 and it returns your LiveData of users. 693 00:30:06,000 --> 00:30:07,650 How it gets the data? 694 00:30:07,650 --> 00:30:10,260 You don't care, it's the repository's job. 695 00:30:10,260 --> 00:30:11,280 So how does it do that? 696 00:30:11,280 --> 00:30:12,420 It talks to the-- 697 00:30:12,420 --> 00:30:15,920 fetching, syncing, looking at database, 698 00:30:15,920 --> 00:30:17,990 or talking to your retrofit back end. 699 00:30:17,990 --> 00:30:20,770 It's the repository's job. 700 00:30:20,770 --> 00:30:23,100 And last but not least, we have our data sources, 701 00:30:23,100 --> 00:30:25,020 like your REST API client. 702 00:30:25,020 --> 00:30:28,470 You might be using Retrofit, or you have SQLite storage. 703 00:30:28,470 --> 00:30:30,500 You might be using Room, or you might be using 704 00:30:30,500 --> 00:30:32,460 GRAM, doesn't really matter. 705 00:30:32,460 --> 00:30:34,920 Or you might be talking to other content providers 706 00:30:34,920 --> 00:30:36,390 from other processes. 707 00:30:36,390 --> 00:30:39,090 These are things we call data sources. 708 00:30:39,090 --> 00:30:41,940 And we think that all of these layers 709 00:30:41,940 --> 00:30:43,830 can discover each other to create 710 00:30:43,830 --> 00:30:45,630 dependency checks to the system which 711 00:30:45,630 --> 00:30:47,370 we'll command using Dagger. 712 00:30:47,370 --> 00:30:49,800 But we also realize that understanding dependency 713 00:30:49,800 --> 00:30:51,810 situation is not very trivial. 714 00:30:51,810 --> 00:30:55,560 It's a more complex topic, and sometimes might be an overkill. 715 00:30:55,560 --> 00:30:57,750 And you could also use a service locator 716 00:30:57,750 --> 00:31:01,560 if you feel more comfortable with it. 717 00:31:01,560 --> 00:31:04,050 So let's go back to-- 718 00:31:04,050 --> 00:31:06,700 go through a concrete example. 719 00:31:06,700 --> 00:31:10,110 Let's say we have a UI that shows a user profile, 720 00:31:10,110 --> 00:31:12,380 and we have the data sources which-- 721 00:31:12,380 --> 00:31:16,080 we save it to database, we also can get it from the network. 722 00:31:16,080 --> 00:31:18,210 How do we connect these two things? 723 00:31:18,210 --> 00:31:21,240 Well, we said we first need a user repository. 724 00:31:21,240 --> 00:31:23,880 User repository knows it should check the database. 725 00:31:23,880 --> 00:31:25,680 It's not there, make a web request. 726 00:31:25,680 --> 00:31:28,500 Or meanwhile, also try to run the database. 727 00:31:28,500 --> 00:31:30,750 It doesn't matter how it does it, 728 00:31:30,750 --> 00:31:32,820 but it knows how to create a LiveData 729 00:31:32,820 --> 00:31:36,780 of a user or an observable, doesn't matter. 730 00:31:36,780 --> 00:31:38,430 And then we need the ViewModel, right, 731 00:31:38,430 --> 00:31:41,670 because the data for the UI lives in the ViewModel. 732 00:31:41,670 --> 00:31:44,220 So we create this ProfileViewModel, 733 00:31:44,220 --> 00:31:48,030 which talks to the repository to get this information. 734 00:31:48,030 --> 00:31:50,850 And then the actual fragment gets the data 735 00:31:50,850 --> 00:31:54,450 from the view model so that if the fragment comes back, 736 00:31:54,450 --> 00:31:57,270 the LiveData will be there in the ProfileViewModel. 737 00:31:57,270 --> 00:32:00,070 But if the fragment disappears completely, 738 00:32:00,070 --> 00:32:01,680 we will get rid of the ViewModel, 739 00:32:01,680 --> 00:32:05,240 and the data can be garbage collected. 740 00:32:05,240 --> 00:32:07,100 Now, all this abstraction we made, 741 00:32:07,100 --> 00:32:10,640 if you notice, every single component only talks to the one 742 00:32:10,640 --> 00:32:14,520 right below it, which is-- helps to scale your application. 743 00:32:14,520 --> 00:32:16,340 It also has a great side benefit, 744 00:32:16,340 --> 00:32:18,260 which is called testing. 745 00:32:18,260 --> 00:32:19,230 You're testing, right? 746 00:32:19,230 --> 00:32:24,500 747 00:32:24,500 --> 00:32:26,210 So let's say you want to test your UI. 748 00:32:26,210 --> 00:32:27,880 Now, people say UI testing is hard. 749 00:32:27,880 --> 00:32:30,990 UI testing is-- yes, it's harder. 750 00:32:30,990 --> 00:32:33,320 But it's usually hard because you put all of your code 751 00:32:33,320 --> 00:32:35,290 into that activity. 752 00:32:35,290 --> 00:32:38,630 Now, we said, put most of it into the ViewModel, 753 00:32:38,630 --> 00:32:41,510 and you know that UI only talks to the ViewModel, 754 00:32:41,510 --> 00:32:43,520 so you can get rid of the other two. 755 00:32:43,520 --> 00:32:47,170 You only need to create a fake ViewModel to test your UI. 756 00:32:47,170 --> 00:32:50,900 Testing your UI become super, super easy with Espresso. 757 00:32:50,900 --> 00:32:52,880 And we have a sample app on GitHub 758 00:32:52,880 --> 00:32:56,346 that you can check out with [INAUDIBLE]. 759 00:32:56,346 --> 00:32:58,220 And the same thing as well as for ViewModels. 760 00:32:58,220 --> 00:32:59,660 If you want to test the ViewModel, 761 00:32:59,660 --> 00:33:02,330 you know it's only talks to the repositories. 762 00:33:02,330 --> 00:33:05,860 You replace it with a mock respository, and it works. 763 00:33:05,860 --> 00:33:08,570 And you can even test your ViewModels 764 00:33:08,570 --> 00:33:11,150 on your host machine, on JVM. 765 00:33:11,150 --> 00:33:12,780 And last but not least, you can test 766 00:33:12,780 --> 00:33:14,030 the respository the same way. 767 00:33:14,030 --> 00:33:16,040 You just mock the data sources. 768 00:33:16,040 --> 00:33:21,000 You can easily test your repositories as JUnit test. 769 00:33:21,000 --> 00:33:23,060 Now, I know this has been a lot of information. 770 00:33:23,060 --> 00:33:26,420 We have two sessions tomorrow, and also documentation. 771 00:33:26,420 --> 00:33:29,630 But now I want to call our product manager lUKAS 772 00:33:29,630 --> 00:33:32,646 to talk about what to do next. 773 00:33:32,646 --> 00:33:35,574 [APPLAUSE] 774 00:33:35,574 --> 00:33:41,425 775 00:33:41,425 --> 00:33:42,800 LUKAS BERGSTROM: Like Yigit said, 776 00:33:42,800 --> 00:33:44,870 we just covered a lot of ground. 777 00:33:44,870 --> 00:33:46,820 And actually, we glossed over a lot of detail 778 00:33:46,820 --> 00:33:48,080 while we did that. 779 00:33:48,080 --> 00:33:50,420 But luckily, you don't have to remember everything 780 00:33:50,420 --> 00:33:51,950 that you just heard. 781 00:33:51,950 --> 00:33:56,180 We have a lot of material for you to check out 782 00:33:56,180 --> 00:33:58,910 at developer.android.com/arch. 783 00:33:58,910 --> 00:34:03,305 And that link should start working in 21 minutes. 784 00:34:03,305 --> 00:34:06,260 785 00:34:06,260 --> 00:34:07,790 We wanted to give you guys a chance 786 00:34:07,790 --> 00:34:10,219 to kind of blog and tweet about this before anybody else. 787 00:34:10,219 --> 00:34:13,190 So that's why we held it back. 788 00:34:13,190 --> 00:34:15,560 So yeah, we made having good documentation 789 00:34:15,560 --> 00:34:18,469 and samples a priority from the beginning of this project, 790 00:34:18,469 --> 00:34:22,310 since providing good guidance is really one of the major goals. 791 00:34:22,310 --> 00:34:24,800 So you're going to find in-depth documentation that's 792 00:34:24,800 --> 00:34:27,337 written from the perspective of an app developer. 793 00:34:27,337 --> 00:34:29,420 You're going to find really meaty sample apps that 794 00:34:29,420 --> 00:34:31,280 show how to build a real app. 795 00:34:31,280 --> 00:34:34,650 And just as an example of how much work went into this, 796 00:34:34,650 --> 00:34:36,139 we have a GitHub browser sample app 797 00:34:36,139 --> 00:34:39,440 that probably has better test coverage than many real world 798 00:34:39,440 --> 00:34:42,170 apps, written by that guy. 799 00:34:42,170 --> 00:34:44,820 800 00:34:44,820 --> 00:34:47,420 And of course, we have the guide to app architecture, 801 00:34:47,420 --> 00:34:50,929 which internally, we called the Opinionated Guide for a while. 802 00:34:50,929 --> 00:34:53,210 And we think that label still applies. 803 00:34:53,210 --> 00:34:55,639 But even if you're not planning to use our recommended 804 00:34:55,639 --> 00:34:58,580 architecture, we think people should check out the guide. 805 00:34:58,580 --> 00:35:04,010 It has principles that we think apply to all apps on Android. 806 00:35:04,010 --> 00:35:07,760 And you're probably asking yourself, do I not-- 807 00:35:07,760 --> 00:35:09,830 what's the impact of this going to be on me? 808 00:35:09,830 --> 00:35:13,160 Am I going to have to change the way that I'm doing everything? 809 00:35:13,160 --> 00:35:15,315 You know, if you're starting a new project, 810 00:35:15,315 --> 00:35:16,940 or if you have an existing app, but you 811 00:35:16,940 --> 00:35:19,190 want to improve the core architecture, 812 00:35:19,190 --> 00:35:22,100 then yeah, we recommend taking a look at this stuff. 813 00:35:22,100 --> 00:35:24,050 It's still preview. 814 00:35:24,050 --> 00:35:26,790 We won't be hitting 1.0 for a few months, 815 00:35:26,790 --> 00:35:30,050 but we think it's definitely ready for you guys 816 00:35:30,050 --> 00:35:32,460 to check out, and use in projects. 817 00:35:32,460 --> 00:35:34,250 But if you're happy with what you have, 818 00:35:34,250 --> 00:35:37,360 you don't need to rewrite your app. 819 00:35:37,360 --> 00:35:39,530 So in the spirit of be together, not the same, 820 00:35:39,530 --> 00:35:41,890 we're not dictating what everyone has to use. 821 00:35:41,890 --> 00:35:44,590 If you're happy with your app architecture, you can keep it. 822 00:35:44,590 --> 00:35:46,510 If you're happy with your existing ORM, 823 00:35:46,510 --> 00:35:48,820 you don't have to use Room. 824 00:35:48,820 --> 00:35:51,910 Architecture components are designed to work well together, 825 00:35:51,910 --> 00:35:55,780 but they do work perfectly fine standalone. 826 00:35:55,780 --> 00:35:58,300 And mixing and matching applies not only 827 00:35:58,300 --> 00:36:04,730 to architecture components, but also third party libraries. 828 00:36:04,730 --> 00:36:11,760 So-- I'm waiting for this slide to come up. 829 00:36:11,760 --> 00:36:14,389 So yeah, so you can use what you have, 830 00:36:14,389 --> 00:36:16,680 and to start to integrate architecture components where 831 00:36:16,680 --> 00:36:18,310 they make sense. 832 00:36:18,310 --> 00:36:21,000 So for example, if you're happy with Rx Java, 833 00:36:21,000 --> 00:36:24,510 but you really like the Lifecycle aware component stuff 834 00:36:24,510 --> 00:36:27,360 that Yigit just showed, so that you have these self-sufficient 835 00:36:27,360 --> 00:36:31,590 components, you can use LiveData together with Rx Java. 836 00:36:31,590 --> 00:36:34,800 So you can get all the power of Rx Java operators, 837 00:36:34,800 --> 00:36:36,420 and now it's Lifecycle safe. 838 00:36:36,420 --> 00:36:39,510 So kind of the best of both worlds. 839 00:36:39,510 --> 00:36:41,760 And we've got additional integrations to come. 840 00:36:41,760 --> 00:36:45,890 We're definitely looking at a lot of stuff internally 841 00:36:45,890 --> 00:36:48,480 that would be nice if it were self-sufficient 842 00:36:48,480 --> 00:36:50,500 and Lifecycle aware. 843 00:36:50,500 --> 00:36:53,460 And if you're a library developer, 844 00:36:53,460 --> 00:36:55,920 we really recommend checking out Lifecycles 845 00:36:55,920 --> 00:36:57,690 and LifecycleObserver because we think 846 00:36:57,690 --> 00:37:00,480 there is a really bright future, and a lot of potential 847 00:37:00,480 --> 00:37:03,420 in making libraries and components that are Lifecycle 848 00:37:03,420 --> 00:37:07,870 aware by default. But before you go 849 00:37:07,870 --> 00:37:11,110 do that, we have a lot more for you at I/O this year. 850 00:37:11,110 --> 00:37:15,310 We have two more talks, one on Lifecycles 851 00:37:15,310 --> 00:37:18,280 that's even more in-depth than what we just showed tomorrow 852 00:37:18,280 --> 00:37:20,020 morning. 853 00:37:20,020 --> 00:37:24,040 We have another one on Room and Persistence, 854 00:37:24,040 --> 00:37:25,480 and going a little bit beyond Room 855 00:37:25,480 --> 00:37:27,790 starting at 12:30 tomorrow. 856 00:37:27,790 --> 00:37:31,950 And we'll have people who are well-versed in architecture 857 00:37:31,950 --> 00:37:36,740 components in the sandbox for all of I/O. 858 00:37:36,740 --> 00:37:41,600 And we also have codelabs, which we're pretty happy with. 859 00:37:41,600 --> 00:37:43,890 And there's more to come. 860 00:37:43,890 --> 00:37:46,100 So we think we've just scratched the surface of ways 861 00:37:46,100 --> 00:37:48,260 that we can improve the experience of using Android 862 00:37:48,260 --> 00:37:51,320 Frameworks, and we're looking at applying this approach 863 00:37:51,320 --> 00:37:53,310 in other areas as well. 864 00:37:53,310 --> 00:37:54,980 So some things already in the works. 865 00:37:54,980 --> 00:37:58,310 And we're also interested in hearing from you on what else 866 00:37:58,310 --> 00:37:59,720 you'd like to see. 867 00:37:59,720 --> 00:38:04,010 So come by, talk to us, tell us what you like, what you don't. 868 00:38:04,010 --> 00:38:06,800 And stay tuned, because we're really excited about the future 869 00:38:06,800 --> 00:38:08,570 of Android development. 870 00:38:08,570 --> 00:38:09,310 Thank you. 871 00:38:09,310 --> 00:38:11,460 [APPLAUSE] 872 00:38:11,460 --> 00:00:00,000 |
1 00:00:00,000 --> 00:00:05,189 [Музыка] 2 00:00:05,189 --> 00:00:05,980 MIKE CLERON: Привет! 3 00:00:05,980 --> 00:00:07,080 Я Майк Клерон. 4 00:00:07,080 --> 00:00:08,650 Я из Android team. 5 00:00:08,650 --> 00:00:14,120 Я разрабатываю UI фреймворк и UI средства разработки [toolkit] 6 00:00:14,120 --> 00:00:17,650 Сегодня мы будем говорить о многих деталях 7 00:00:17,650 --> 00:00:21,790 и о некоторых больших изменениях в подходах, которые мы рекомендуем 8 00:00:21,790 --> 00:00:23,710 при проектировании приложений для Android. 9 00:00:23,710 --> 00:00:26,110 Но прежде чем мы погрузимся в детали, 10 00:00:26,110 --> 00:00:28,510 я думаю, что будет полезно сделать шаг в сторону, 11 00:00:28,510 --> 00:00:31,960 и поговорить о том, откуда мы пришли 12 00:00:31,960 --> 00:00:34,730 и куда мы идем. 13 00:00:34,730 --> 00:00:36,100 Давайте начнем. 14 00:00:36,100 --> 00:00:39,010 Итак, Android всегда основывался на 15 00:00:39,010 --> 00:00:41,230 на нескольких прочных принципах 16 00:00:41,230 --> 00:00:43,330 Не удивительно, они были лучше всего выражены 17 00:00:43,330 --> 00:00:44,860 Дианой Хакборн. 18 00:00:44,860 --> 00:00:46,600 Она из тех, кто реально проектировали 19 00:00:46,600 --> 00:00:48,880 большую часть Android фреймворков. 20 00:00:48,880 --> 00:00:51,160 Она написала пост об этом несколько месяцев назад, 21 00:00:51,160 --> 00:00:54,310 и у меня есть некоторые выдержки оттуда. 22 00:00:54,310 --> 00:00:56,230 Если вы посмотрите на примитивы ядра Android -- 23 00:00:56,230 --> 00:01:00,100 Activity, BroadcastReceiver, Service, ContentProvider, 24 00:01:00,100 --> 00:01:03,880 у вас есть основание думать, что они составляют каркас 25 00:01:03,880 --> 00:01:05,012 приложения (framework). 26 00:01:05,012 --> 00:01:06,970 Но это не верный способ думать об этом. 27 00:01:06,970 --> 00:01:10,120 Эти классы фактически контракты 28 00:01:10,120 --> 00:01:14,910 между приложением и операционной системой (ОС). 29 00:01:14,910 --> 00:01:16,950 Они представляют собой минимальное количество информации 30 00:01:16,950 --> 00:01:20,790 необходимое, чтобы ОС знала, что происходит внутри вашего приложения 31 00:01:20,790 --> 00:01:23,220 т.о. мы можем управлять этим правильно. 32 00:01:23,220 --> 00:01:27,060 Итак, для примера, если ваше приложение работает в фоне, 33 00:01:27,060 --> 00:01:29,600 но также предоставляет данные другому приложению 34 00:01:29,600 --> 00:01:32,492 через ContentProvider, то ОС должна об этом знать. 35 00:01:32,492 --> 00:01:34,950 И мы должны знать, что случайно не убьем его. 36 00:01:34,950 --> 00:01:37,500 ContentProvider это механизм который говорит нам, 37 00:01:37,500 --> 00:01:39,990 что мы должны держать вас живыми. 38 00:01:39,990 --> 00:01:41,970 Итак, мы думаем об этих основных классах 39 00:01:41,970 --> 00:01:44,790 как действительно существующих подобно фундаментальным законам физики 40 00:01:44,790 --> 00:01:47,520 для Android. Тогда иллюстрация. 41 00:01:47,520 --> 00:01:49,920 Это обложка книги, где впервые 42 00:01:49,920 --> 00:01:52,170 Исаак Ньютон описал 43 00:01:52,170 --> 00:01:53,430 фундаментальные законы движения. 44 00:01:53,430 --> 00:01:56,620 45 00:01:56,620 --> 00:01:59,580 Теперь, фундаментальные законы это отличная вещь. 46 00:01:59,580 --> 00:02:01,560 Я использую условные обозначения Когда говорю об этом. 47 00:02:01,560 --> 00:02:04,530 Я говорю "У Android хорошие кости", даже если люди смотрят на меня 48 00:02:04,530 --> 00:02:06,780 с усмешкой после этого. 49 00:02:06,780 --> 00:02:09,960 Но что я имею в виду, когда говорю, что Android это Android 50 00:02:09,960 --> 00:02:13,650 он небольшой, стабильный, имеет связанный набор 51 00:02:13,650 --> 00:02:15,150 примитивов ядра. 52 00:02:15,150 --> 00:02:18,390 И это позволяет иметь общую программную модель Android 53 00:02:18,390 --> 00:02:20,940 на очень широком диапазоне различных устройств 54 00:02:20,940 --> 00:02:24,750 от носимых устройств, телефонов, планшетов 55 00:02:24,750 --> 00:02:27,870 до ТВ, автомобилей и т.д. 56 00:02:27,870 --> 00:02:30,210 И эта же модель дает разработчикам приложений 57 00:02:30,210 --> 00:02:32,310 свободу выбора любого фреймворка 58 00:02:32,310 --> 00:02:34,170 какой они хотят использовать для своего приложения 59 00:02:34,170 --> 00:02:36,010 для их внутренней структуры. 60 00:02:36,010 --> 00:02:38,070 Это означает, что нам в команде Android 61 00:02:38,070 --> 00:02:41,250 не следует заниматься дебатами что лучше: MVC 62 00:02:41,250 --> 00:02:45,540 или MVP, или что MVP лучше чем [? MVVBM. ?] 63 00:02:45,540 --> 00:02:49,260 Вы, ребята, выбирайте что угодно что имеет смысл для вас. 64 00:02:49,260 --> 00:02:52,680 И это звучит хорошо для нас, находящихся 65 00:02:52,680 --> 00:02:55,921 в разработке ОС, как я 66 00:02:55,921 --> 00:02:57,420 Но если вы разработчик приложений 67 00:02:57,420 --> 00:03:01,110 скажем, каждый из вас. Что ж, тогда 68 00:03:01,110 --> 00:03:03,120 это только одна глава в этой истории. 69 00:03:03,120 --> 00:03:04,890 И причина в том, что хотя 70 00:03:04,890 --> 00:03:08,190 строгие фундаментальные основы и свобода выбора [реализации] 71 00:03:08,190 --> 00:03:12,000 это хорошие вещи, мы знаем, что в повседневной работе [этого мало]- 72 00:03:12,000 --> 00:03:16,730 и мы знаем это потому, что вы говорите, что хотите большего от нас. 73 00:03:16,730 --> 00:03:19,690 Так что я буду немного надоедать моей аналогией. 74 00:03:19,690 --> 00:03:22,810 Мы все можем оценить простую элегантность законов Ньютона 75 00:03:22,810 --> 00:03:27,725 о движении, но если вы собираетесь высадить марсоход на Марс, 76 00:03:27,725 --> 00:03:29,350 вам не захочется, приходить на работу каждый день и 77 00:03:29,350 --> 00:03:31,810 и начинать с того, что сила равна масса на ускорение, и получить все 78 00:03:31,810 --> 00:03:35,230 из оснований классической механики Ньютона. 79 00:03:35,230 --> 00:03:37,780 Итак, мы поговорили с разработчиками с обеих сторон, внутри 80 00:03:37,780 --> 00:03:41,140 и вне Google, и при этом внимательно изучали 81 00:03:41,140 --> 00:03:42,830 опыт разработки приложений. 82 00:03:42,830 --> 00:03:45,230 И нам удалось понять несколько вещей. 83 00:03:45,230 --> 00:03:47,770 Первое, у нас есть вершины и есть долины. 84 00:03:47,770 --> 00:03:51,550 Некоторые аспекты разработки прекрасно обслуживаются нашими API 85 00:03:51,550 --> 00:03:52,570 другие - хуже. 86 00:03:52,570 --> 00:03:56,470 Например, мы думаем, что RecyclerView это лучшая вершина 87 00:03:56,470 --> 00:03:57,830 из этого спектра. 88 00:03:57,830 --> 00:04:02,020 С RecyclerView, мы не говорим: эй, мы даем вам события, 89 00:04:02,020 --> 00:04:03,810 и вы можете рисовать вещи. 90 00:04:03,810 --> 00:04:07,600 И у вас есть тьюринг-полный язык, так что удачи 91 00:04:07,600 --> 00:04:09,550 со всем остальным! 92 00:04:09,550 --> 00:04:12,640 С другой стороны, возможно жизненные циклы 93 00:04:12,640 --> 00:04:16,510 Activity и Fragment принадлежат к темным впадинам 94 00:04:16,510 --> 00:04:18,730 потому что там, я думаю, оставлено действительно 95 00:04:18,730 --> 00:04:21,790 слишком много упражнений для читателя [необходимо много читать]. 96 00:04:21,790 --> 00:04:24,730 И мы хотим исправить это. 97 00:04:24,730 --> 00:04:27,250 Итак, мы думаем, что хорошее решение имеет 98 00:04:27,250 --> 00:04:29,930 ключевые свойства. 99 00:04:29,930 --> 00:04:32,194 Во-первых, мы обязаны находить правильные проблемы. 100 00:04:32,194 --> 00:04:33,860 И это будет непрерывным усилием -- 101 00:04:33,860 --> 00:04:36,320 так же как и с нашей стороны для нас на Android. 102 00:04:36,320 --> 00:04:38,410 Но для первого сокращения, мы хотим убедиться, 103 00:04:38,410 --> 00:04:39,910 что мы будем решать проблемы, с которыми 104 00:04:39,910 --> 00:04:42,040 сталкивается каждый разработчик. Те, которые трудно решить 105 00:04:42,040 --> 00:04:45,040 прямо сейчас. Опять же, 106 00:04:45,040 --> 00:04:47,574 жизненный цикл приложения - на самом деле хороший пример. 107 00:04:47,574 --> 00:04:49,240 Если вы не получите это право [управлять циклом] в своем приложении, 108 00:04:49,240 --> 00:04:51,236 на нем ничего не будет работать. 109 00:04:51,236 --> 00:04:53,110 Это верно для вашего приложения, но так же 110 00:04:53,110 --> 00:04:55,026 верно для фреймворков, которые мы пытаемся создавать. 111 00:04:55,026 --> 00:04:58,420 Мы должны получить это право до того как можем сделать что-нибудь еще. 112 00:04:58,420 --> 00:05:00,370 Второе, мы должны хорошо координировать свою работу с другими. 113 00:05:00,370 --> 00:05:02,830 Мы знаем, что вы здорово вкладываетесь в существующие 114 00:05:02,830 --> 00:05:05,196 модели программирования, и мы не можем создать модель, 115 00:05:05,196 --> 00:05:06,820 где сразу скажем вам, чтобы вы, 116 00:05:06,820 --> 00:05:08,940 бросили все старое и начали сначала. 117 00:05:08,940 --> 00:05:12,070 Итак, мы стараемся создать API, на которое вы не потратите много 118 00:05:12,070 --> 00:05:15,580 времени, и также которое хорошо взаимодействует 119 00:05:15,580 --> 00:05:19,710 с другими библиотеками и другими фреймворками. 120 00:05:19,710 --> 00:05:22,054 В-третьих, мы хотим быть более настойчивыми. 121 00:05:22,054 --> 00:05:23,970 Мы собираемся занять более сильную и четкую позицию 122 00:05:23,970 --> 00:05:26,000 о том, каким должен быть правильный путь развития Android, 123 00:05:26,000 --> 00:05:27,100 По крайней мере, как мы это видим. 124 00:05:27,100 --> 00:05:29,100 Теперь, это все еще необязательно. 125 00:05:29,100 --> 00:05:31,330 И если у вас уже есть, то, что работает для вас, 126 00:05:31,330 --> 00:05:33,030 то это здорово. 127 00:05:33,030 --> 00:05:36,210 Но разработчики говорят нам, что хотели бы большей ясности о том, 128 00:05:36,210 --> 00:05:38,590 как следует строить приложения. И к слову 129 00:05:38,590 --> 00:05:40,770 мы не меняем "законов физики" [core Android] здесь, 130 00:05:40,770 --> 00:05:43,860 мы просто меняем конструкции более высокого уровня. 131 00:05:43,860 --> 00:05:46,620 Потому что сила будет равна масса умножить на ускорение несмотря на то 132 00:05:46,620 --> 00:05:49,860 верите ли вы в это или нет. 133 00:05:49,860 --> 00:05:52,140 Следующее, необходимо масштабировать. 134 00:05:52,140 --> 00:05:54,420 Нам нужны решения, которые обладают индустриальной мощью 135 00:05:54,420 --> 00:05:56,760 и могут масштабироваться под реальные мировые требования 136 00:05:56,760 --> 00:05:58,474 реальных приложений. 137 00:05:58,474 --> 00:06:01,140 Мы не хотим создавать что-то, что хорошо работает для Hello World, 138 00:06:01,140 --> 00:06:03,181 но сдает позиции сразу же при первом использовании, 139 00:06:03,181 --> 00:06:07,620 когда сталкивается с суровой, сложной реальностью. 140 00:06:07,620 --> 00:06:09,410 И наконец, поддержка и обогащение [версий Android]. 141 00:06:09,410 --> 00:06:11,310 Для [решения] этой проблемы, для упрощения 142 00:06:11,310 --> 00:06:13,830 написания приложений Android правильным способом -- 143 00:06:13,830 --> 00:06:15,690 мы думаем, что будет правильным 144 00:06:15,690 --> 00:06:18,390 использовать библиотеки наподобие Support Lib где это только возможно, 145 00:06:18,390 --> 00:06:21,150 а не добавлять новые API на платформу, 146 00:06:21,150 --> 00:06:24,030 потому что таким образом мы сможем обогатить старые версии ОС 147 00:06:24,030 --> 00:06:26,745 так же. 148 00:06:26,745 --> 00:06:29,370 OK, это то на чем мы основываемся, что, что мы пытаемся осуществить, 149 00:06:29,370 --> 00:06:30,440 и почему мы находимся здесь. 150 00:06:30,440 --> 00:06:33,309 Теперь мы бы хотели представить Yigit, инженера средств разработки. 151 00:06:33,309 --> 00:06:35,600 И он собирается рассказать вам как мы это 152 00:06:35,600 --> 00:06:36,860 осуществляли на практике. Спасибо. 153 00:06:36,860 --> 00:06:37,290 [АПЛОДИСМЕНТЫ] 154 00:06:37,290 --> 00:06:38,248 YIGIT BOYAR: Хорошо. 155 00:06:38,248 --> 00:06:39,322 Спасибо, Frank. 156 00:06:39,322 --> 00:06:43,610 157 00:06:43,610 --> 00:06:44,410 Привет всем. 158 00:06:44,410 --> 00:06:46,930 Итак, это было то, на чем мы основываемся. 159 00:06:46,930 --> 00:06:49,050 К чему мы идем сегодня? 160 00:06:49,050 --> 00:06:51,210 Первая вещь к которой мы идем 161 00:06:51,210 --> 00:06:55,230 это руководство по архитектуре на developer Android com. 162 00:06:55,230 --> 00:06:58,440 На протяжении многих лет вы спрашивали наше мнение, 163 00:06:58,440 --> 00:07:02,220 как по-нашему приложение должно быть построено? 164 00:07:02,220 --> 00:07:03,900 И это и есть это руководство. 165 00:07:03,900 --> 00:07:06,270 И мы считаем, что оно достаточно хорошо, 166 00:07:06,270 --> 00:07:08,730 и покрывает большинство видов приложений. 167 00:07:08,730 --> 00:07:10,890 Но даже если вы имеете свою архитектуру 168 00:07:10,890 --> 00:07:14,040 которая удобна для вас, вы можете сохранять ее. 169 00:07:14,040 --> 00:07:18,300 Но вы можете попробовать узнать что-то новое из этого руководства 170 00:07:18,300 --> 00:07:20,910 Во-вторых, мы движемся к созданию нового набора библиотек, 171 00:07:20,910 --> 00:07:23,290 которые мы называем архитектурные компоненты. 172 00:07:23,290 --> 00:07:24,900 Это более фундаментальные компоненты [строительные блоки] 173 00:07:24,900 --> 00:07:28,440 на которых вы можете основывать ваше приложение. 174 00:07:28,440 --> 00:07:29,760 Первая вещь - жизненный цикл. 175 00:07:29,760 --> 00:07:33,000 Это самая частая жалоба, которую мы получаем от разработчиков. 176 00:07:33,000 --> 00:07:35,610 Жизненный цикл сложен, Жизненный цикл сложен. 177 00:07:35,610 --> 00:07:38,020 И мы сказали "ОК", нам следует решить эту проблему. 178 00:07:38,020 --> 00:07:41,850 И первый шаг для этого, это новый набор компонентов. 179 00:07:41,850 --> 00:07:44,070 Второе - это учитывающие жизненный цикл Observables, 180 00:07:44,070 --> 00:07:46,860 которые в деталях будут рассмотрены позже, но базово это 181 00:07:46,860 --> 00:07:51,730 сделать что-то, базируясь на жизненном цикле. 182 00:07:51,730 --> 00:07:54,810 В-третьих, мы собираемся представить легковесные ViewModel, которые 183 00:07:54,810 --> 00:07:58,020 помогут вывести ваш код 184 00:07:58,020 --> 00:08:00,150 наружу из ваших Activities и Fragments, 185 00:08:00,150 --> 00:08:03,550 и поместить его где-нибудь еще, где вы сможете легко протестировать его. 186 00:08:03,550 --> 00:08:06,630 И последнее, но не менее важное, мы собираемся представить новый объект 187 00:08:06,630 --> 00:08:10,290 mapping library для SQLite. 188 00:08:10,290 --> 00:08:15,248 И все это доступно для вас сегодня на Maven Google com. 189 00:08:15,248 --> 00:08:24,290 [АПЛОДИСМЕНТЫ] 190 00:08:24,290 --> 00:08:25,790 Давайте поговорим о жизненных циклах. 191 00:08:25,790 --> 00:08:27,830 Итак, что же сложного в жизненных циклах? 192 00:08:27,830 --> 00:08:29,970 Почему мы слышим так много жалоб об этом? 193 00:08:29,970 --> 00:08:31,510 Давайте перейдем к примеру. 194 00:08:31,510 --> 00:08:33,440 Предположим, что у нас есть Activity где мы 195 00:08:33,440 --> 00:08:36,591 хотим выводить местоположение устройства на экран. 196 00:08:36,591 --> 00:08:38,090 Итак, вы попробуете сделать что-то вроде этого. 197 00:08:38,090 --> 00:08:41,280 Вы создадите LocationListener в методе onCreate(), 198 00:08:41,280 --> 00:08:43,250 вам нужно будет инициализировать его контекстом [Context], 199 00:08:43,250 --> 00:08:46,520 и у вас будет обратный вызов [callback], который вызывается всякий раз, когда 200 00:08:46,520 --> 00:08:48,800 локация меняется, и вы обновляете UI. 201 00:08:48,800 --> 00:08:51,230 Теперь, если вы когда-либо писали приложение на Android, 202 00:08:51,230 --> 00:08:54,330 вы знаете, что этого кода недостаточно. 203 00:08:54,330 --> 00:08:57,440 Вам также нужно пойти дальше и переопределить onStart(), и затем 204 00:08:57,440 --> 00:09:01,880 дать команду начинать, и переопределить onStop(), и дать команду остановиться. 205 00:09:01,880 --> 00:09:04,040 Вы всегда должны таким образом присматривать 206 00:09:04,040 --> 00:09:05,510 за этими компонентами. 207 00:09:05,510 --> 00:09:06,840 Но это приемлемо. 208 00:09:06,840 --> 00:09:09,680 Это простой пример, это выглядит хорошо. 209 00:09:09,680 --> 00:09:11,750 Но тогда появляется ваш Product Manager и говорит, 210 00:09:11,750 --> 00:09:12,560 "О, ды та знаешь что?" 211 00:09:12,560 --> 00:09:16,160 "Нам необходимо проверить сначала настройки пользователя перед разрешением-- 212 00:09:16,160 --> 00:09:17,710 спрашивать о местоположении." 213 00:09:17,710 --> 00:09:22,160 Тогда вам разработчик скажет "OK" конечно, "Это просто изменить." 214 00:09:22,160 --> 00:09:25,570 "Я изменю этот метод, который будет вызывать утилиту, 215 00:09:25,570 --> 00:09:27,980 которая, вероятно, сделает запрос к веб-сервису 216 00:09:27,980 --> 00:09:29,900 и проверить настройки пользователя. 217 00:09:29,900 --> 00:09:32,030 И тогда, если пользователь зарегистрирован, 218 00:09:32,030 --> 00:09:34,160 мы запустим наш LocationListener." 219 00:09:34,160 --> 00:09:37,010 Это похоже на очень простое изменение, 220 00:09:37,010 --> 00:09:39,440 вы подумаете, что это могло бы сработать, но давайте посмотрим, 221 00:09:39,440 --> 00:09:42,440 что происходит в жизненном цикле этой Activity. 222 00:09:42,440 --> 00:09:43,990 Итак наша Activity была создана. 223 00:09:43,990 --> 00:09:49,526 Мы говорим "OK", запускаем проверку зарегистрирован ли пользователь. 224 00:09:49,526 --> 00:09:52,370 Но вдруг, пользователь захотел повернуть устройство. 225 00:09:52,370 --> 00:09:54,930 И поворот означает смену конфигурации, 226 00:09:54,930 --> 00:09:58,430 что означает, что Android начнет пересоздавать Activity. 227 00:09:58,430 --> 00:10:00,200 Итак в onStop(), мы узнаем об этом, 228 00:10:00,200 --> 00:10:03,292 и мы скажем "OK" location manager остановился. 229 00:10:03,292 --> 00:10:05,780 И затем появляется новая Activity, и она также 230 00:10:05,780 --> 00:10:07,430 проходит через то же самое. 231 00:10:07,430 --> 00:10:10,280 Выглядит хорошо, исключая, как вы помните, наш запрос, 232 00:10:10,280 --> 00:10:12,140 который мы сделали до того. 233 00:10:12,140 --> 00:10:15,400 Это маленькое изменение [поворот], и затем запрос возвращает ответ. 234 00:10:15,400 --> 00:10:17,110 "Эй, пользователь зарегистрирован". 235 00:10:17,110 --> 00:10:18,080 И что мы тогда делаем? 236 00:10:18,080 --> 00:10:20,790 Мы скажем "OK, стартуй!". 237 00:10:20,790 --> 00:10:22,250 И вы осознаете [НЕРАЗБОРЧИВО]? 238 00:10:22,250 --> 00:10:26,510 Мы вызываем onStart() после вызова onStop(), это означает, 239 00:10:26,510 --> 00:10:28,700 наша Activity будет жить вечно. 240 00:10:28,700 --> 00:10:31,130 Мы будем наблюдать это местоположение вечно, 241 00:10:31,130 --> 00:10:32,257 пока батарея не разрядится. 242 00:10:32,257 --> 00:10:33,215 Мы опечалим наших пользователей. 243 00:10:33,215 --> 00:10:37,078 244 00:10:37,078 --> 00:10:38,600 Знакомая ситуация, не так ли? 245 00:10:38,600 --> 00:10:40,220 Мы хотим избавиться от этого. 246 00:10:40,220 --> 00:10:41,840 Мы хотим положить этому конец. 247 00:10:41,840 --> 00:10:43,950 Итак, мы говорим "OK", нам нужно признать - 248 00:10:43,950 --> 00:10:46,670 как упоминал Майк, мы не можем изменить законы. 249 00:10:46,670 --> 00:10:49,670 Но мы можем поступить проще: иметь дело с вещами. 250 00:10:49,670 --> 00:10:52,430 Поэтому мы решили ввести новый интерфейс называемый 251 00:10:52,430 --> 00:10:53,970 LifecycleOwner. 252 00:10:53,970 --> 00:10:55,970 Эта вещь идет вместе с жизненным циклом. 253 00:10:55,970 --> 00:10:58,400 Если у вас Activity, или ваш Fragment - или, возможно, 254 00:10:58,400 --> 00:11:02,270 ваш собственный UI фреймворк, независимо от того, что у вас есть, 255 00:11:02,270 --> 00:11:05,570 это можно представить, как LifecycleOwner. 256 00:11:05,570 --> 00:11:08,780 И у нас есть [наблюдатели] LifecycleObservers, 257 00:11:08,780 --> 00:11:11,180 цель которых заботиться о жизненном цикле. 258 00:11:11,180 --> 00:11:13,310 Как и в LocationListener у нас было, 259 00:11:13,310 --> 00:11:16,580 он заботится о жизненном цикле, хочет остановить себя 260 00:11:16,580 --> 00:11:18,680 Если жизненный цикл не активен. 261 00:11:18,680 --> 00:11:21,130 Итак, мы сказали "OK, мы признаем это. 262 00:11:21,130 --> 00:11:23,600 И у нас есть LifecycleObservers." 263 00:11:23,600 --> 00:11:26,090 Мы пройдем через код в нашей Acivity. 264 00:11:26,090 --> 00:11:30,080 Сейчас мы наследуем нашу Activity от класса LifecycleActivity. 265 00:11:30,080 --> 00:11:33,320 Это лишь временный класс пока эти компоненты дойдут 266 00:11:33,320 --> 00:11:34,410 до версии 1.0. 267 00:11:34,410 --> 00:11:35,900 Затем все в Support Library 268 00:11:35,900 --> 00:11:39,980 реализует интерфейс LifecycleOwner. 269 00:11:39,980 --> 00:11:42,550 Внутри нашей Activity, где мы инициализируем 270 00:11:42,550 --> 00:11:45,710 наш LocationListener, мы собираемя сказать, что 271 00:11:45,710 --> 00:11:48,240 это наш жизненный цикл, о котором мы заботимся. 272 00:11:48,240 --> 00:11:50,390 И это все, что мы делаем. 273 00:11:50,390 --> 00:11:54,410 Но поскольку это то же самое, он вызывает обновление UI. 274 00:11:54,410 --> 00:11:57,020 Итак, как мы можем изменить наш LocationListener 275 00:11:57,020 --> 00:12:00,890 используя преимущества этого жизненного цикла? 276 00:12:00,890 --> 00:12:03,500 О, мы делаем тоже самое для UserStatus также. 277 00:12:03,500 --> 00:12:06,240 278 00:12:06,240 --> 00:12:08,880 Итак, есть некоторые шаблоны кода здесь, чтобы получить поля. 279 00:12:08,880 --> 00:12:10,950 Это на самом деле не важно, но у нас есть 280 00:12:10,950 --> 00:12:14,850 этот метод, enable(), который вызывается, если пользователь зарегистрирован. 281 00:12:14,850 --> 00:12:16,500 Внутри этого метода мы теперь 282 00:12:16,500 --> 00:12:18,420 хотим начать отслеживать местоположение 283 00:12:18,420 --> 00:12:21,360 только, если Activity запущена. 284 00:12:21,360 --> 00:12:23,040 Теперь вы можете сделать это. 285 00:12:23,040 --> 00:12:26,590 Вы можете узнать, какое ваше текущее состояние, и это удивительно. 286 00:12:26,590 --> 00:12:29,370 У нас не было такого API до сих пор. 287 00:12:29,370 --> 00:12:32,010 Ну, теперь вы можете это. 288 00:12:32,010 --> 00:12:34,110 Итак, хорошо, это было простое изменение. 289 00:12:34,110 --> 00:12:36,510 Но мы также получаем уведомление, что мы зарегистрированы, 290 00:12:36,510 --> 00:12:38,710 когда Activity будет не в активном состоянии, 291 00:12:38,710 --> 00:12:40,800 и пользователь вернется к Activity. 292 00:12:40,800 --> 00:12:43,290 Теперь нам следует на самом деле запустить LocationManager. 293 00:12:43,290 --> 00:12:46,290 Для этого мы хотим наблюдать за жизненным циклом. 294 00:12:46,290 --> 00:12:48,690 Здесь мы имплементируем этот интерфейс, 295 00:12:48,690 --> 00:12:50,670 который позволяет нам использовать эти методы. 296 00:12:50,670 --> 00:12:52,710 Вы можете аннотировать эти методы, говоря что, 297 00:12:52,710 --> 00:12:56,152 если ON_START случился, вызывай этот метод. 298 00:12:56,152 --> 00:12:58,360 И новые компоненты будут заботиться о вызовах. 299 00:12:58,360 --> 00:13:00,660 Итак, если вы теперь доступны, то теперь вы начинаете, 300 00:13:00,660 --> 00:13:03,540 и если ON_STOP вы отключаетесь. 301 00:13:03,540 --> 00:13:06,700 И последнее по порядку, но не по значимости, Если Activity остановлено и уничтожено, 302 00:13:06,700 --> 00:13:09,220 вам ничего не нужно делать с этой Activity 303 00:13:09,220 --> 00:13:11,796 Вы можете разрегистрироваться. 304 00:13:11,796 --> 00:13:13,920 Итак, вы тогда можете скать себе: "Хорошо, вы просто 305 00:13:13,920 --> 00:13:16,710 перенесли эти ON_START, ON_STOP методы из Activity 306 00:13:16,710 --> 00:13:18,450 в Location Manager. 307 00:13:18,450 --> 00:13:20,150 Почему это проще?" 308 00:13:20,150 --> 00:13:22,250 Это проще потому, что эти методы 309 00:13:22,250 --> 00:13:23,610 находятся в правильном месте. 310 00:13:23,610 --> 00:13:27,690 И это LocationManager, который заботиться о жизненном цикле. 311 00:13:27,690 --> 00:13:30,780 И это следует делать без того, чтобы Activity 312 00:13:30,780 --> 00:13:32,460 нянчила сама себя. 313 00:13:32,460 --> 00:13:34,170 Я уверен, если вы посмотрите в ваш код сегодня, 314 00:13:34,170 --> 00:13:37,260 в вашей Activity методы ON_START, ON_STOP, будут занимать, 315 00:13:37,260 --> 00:13:38,730 не менее 20-30 строк кода. 316 00:13:38,730 --> 00:13:42,060 Мы хотим, чтобы они занимали 0 строк кода. 317 00:13:42,060 --> 00:13:43,800 И если мы вернемся к Activity, я хочу указать 318 00:13:43,800 --> 00:13:45,780 на кое-что - 319 00:13:45,780 --> 00:13:49,260 Смотрите, в onCreate(), мы инициализируем эти компоненты. 320 00:13:49,260 --> 00:13:50,580 И это все, что мы делаем. 321 00:13:50,580 --> 00:13:53,230 Мы не переопределяем, мы не пишем ON_STOP, ON_START, 322 00:13:53,230 --> 00:13:55,020 мы не переопределяем никакие из этих сущностей, 323 00:13:55,020 --> 00:13:59,630 потому что LocationManager это компонент, осведомленный о жизненном цикле 324 00:13:59,630 --> 00:14:01,875 теперь. 325 00:14:01,875 --> 00:14:03,990 Итак, это новая концепция, которую мы хотим представить. 326 00:14:03,990 --> 00:14:08,130 Компонент осведомленный о жизненном цикле, может получить его состояние, 327 00:14:08,130 --> 00:14:09,170 и поступать правильно таким образом. 328 00:14:09,170 --> 00:14:12,210 Он может заботиться о себе сам, так что в вашей Activity 329 00:14:12,210 --> 00:14:15,120 вы можете просто инициализировать это и забыть об этом. 330 00:14:15,120 --> 00:14:19,060 Вы можете не беспокоиться, что это утечет от вас. 331 00:14:19,060 --> 00:14:22,480 Теперь, конечно, это было похоже на перемещение комплекса 332 00:14:22,480 --> 00:14:24,520 из Activity в LocationManager, 333 00:14:24,520 --> 00:14:27,310 и затем все еще нужно иметь дело с жизненным циклом. 334 00:14:27,310 --> 00:14:29,190 Мы сказали "OK, чего мы хотим?" 335 00:14:29,190 --> 00:14:32,540 Это приятно суметь сделать это, но мы хотим большего. 336 00:14:32,540 --> 00:14:35,230 Мы хотим больше удобства для обработки этого общего случая. 337 00:14:35,230 --> 00:14:38,390 Довольно часто бывает, что ваша Activity или Fragment 338 00:14:38,390 --> 00:14:41,830 наблюдают некоторые данные, и всякий раз, когда данные меняются, 339 00:14:41,830 --> 00:14:43,300 они хотят обновить свое состояние. 340 00:14:43,300 --> 00:14:46,910 Это случается практически в каждом пользовательском UI. 341 00:14:46,910 --> 00:14:49,870 И мы хотим подеиться ресурсами через несколько Fragments 342 00:14:49,870 --> 00:14:51,250 или Activities. 343 00:14:51,250 --> 00:14:54,580 Местоположение устройства одинаково от фрагмента 344 00:14:54,580 --> 00:14:55,240 к фрагменту. 345 00:14:55,240 --> 00:14:57,040 И если у вас два Fragment'a, почему вы должны создавать 346 00:14:57,040 --> 00:15:01,610 два Listener'a, чтобы слушать одно и то же местоположение? 347 00:15:01,610 --> 00:15:05,080 Следовательно, мы создали новую штуку: LiveData. 348 00:15:05,080 --> 00:15:06,600 Давайте посмотрим что это. 349 00:15:06,600 --> 00:15:10,390 Итак, LiveData это держатель данных, он просто содержит некоторые данные. 350 00:15:10,390 --> 00:15:13,690 Это похоже на слушателя, но LiveData более хитрая вещь, 351 00:15:13,690 --> 00:15:15,760 которая знает о жизненном цикле. 352 00:15:15,760 --> 00:15:18,310 Он понимает жизненный цикл. 353 00:15:18,310 --> 00:15:20,820 Он понимает о жизненном цикле потому, 354 00:15:20,820 --> 00:15:22,850 что автоматически управляет подписками. 355 00:15:22,850 --> 00:15:25,220 Так что очень похоже на предыдущий пример, 356 00:15:25,220 --> 00:15:29,290 и если вы наблюдаете LiveData, вам нет необходимости отписываться. 357 00:15:29,290 --> 00:15:33,040 Нужные вещи будут происходить в нужное время. 358 00:15:33,040 --> 00:15:37,660 Так что если бы LocationListener был LiveData, и был singleton 359 00:15:37,660 --> 00:15:40,000 потому что метоположение это singleton, мы могли бы 360 00:15:40,000 --> 00:15:41,800 написать что-то вроде этого - 361 00:15:41,800 --> 00:15:43,930 getInstance(), начать наблюдение. 362 00:15:43,930 --> 00:15:47,280 И когда вы наблюдаете, вы говорите: "Это мой жизненный цикл". 363 00:15:47,280 --> 00:15:48,280 Это все, что вам нужно сделать. 364 00:15:48,280 --> 00:15:51,880 Раньше на Android, если вы наблюдали что-то, что было singleton 365 00:15:51,880 --> 00:15:55,180 из Activity, каждый снизит вам два балла 366 00:15:55,180 --> 00:15:56,650 при обзоре этого кода. 367 00:15:56,650 --> 00:15:57,805 Теперь вы можете делать это. 368 00:15:57,805 --> 00:16:01,600 Это безопасно, это не грозит утечками. 369 00:16:01,600 --> 00:16:03,790 Итак, если вы захотите изменить ваш LocationListener 370 00:16:03,790 --> 00:16:07,430 используйте это API, мы избавились от ненужных вещей. 371 00:16:07,430 --> 00:16:09,590 Все, что нам нужно, Это Context для подключения. 372 00:16:09,590 --> 00:16:15,540 Что мы говорим: это LiveData, это LiveData местоположения. 373 00:16:15,540 --> 00:16:18,110 и мы даем эти два новых метода. 374 00:16:18,110 --> 00:16:20,520 Один из двух называется onActive(), что значит 375 00:16:20,520 --> 00:16:22,920 у вас есть активный наблюдатель. 376 00:16:22,920 --> 00:16:24,475 Другой называется onInactive(), 377 00:16:24,475 --> 00:16:27,555 что означает, что у вас нет ни одного активного наблюдателя. 378 00:16:27,555 --> 00:16:30,360 Теперь, на данный момент, вы, возможно, спрашиваете себя: 379 00:16:30,360 --> 00:16:32,590 "Что такое активный наблюдатель?" 380 00:16:32,590 --> 00:16:34,290 Хорошо, мы дадим определение активному наблюдателю. 381 00:16:34,290 --> 00:16:37,710 Это наблюдатель который находится в состоянии START или RESUME, который 382 00:16:37,710 --> 00:16:40,440 как пользователь Activity, в настоящее время смотрит. 383 00:16:40,440 --> 00:16:43,020 Итак, если у вас есть наблюдатель на заднем фоне, 384 00:16:43,020 --> 00:16:45,300 Нет никаких оснований полагать что она не активна. 385 00:16:45,300 --> 00:16:47,190 Нет причин обновлять Activity 386 00:16:47,190 --> 00:16:49,950 потому что пользователь никогда не увидит, что там происходит. 387 00:16:49,950 --> 00:16:53,390 388 00:16:53,390 --> 00:16:56,130 Т.к. внутри нашего метода connect(), все, что мы должны сделать 389 00:16:56,130 --> 00:16:58,540 это всякий раз, когда LocationManager отправляет нам 390 00:16:58,540 --> 00:17:02,120 новое местоположение, мы вызываем setValue() с ним. 391 00:17:02,120 --> 00:17:05,589 Тогда LiveData знает какие наблюдатели активны, 392 00:17:05,589 --> 00:17:08,410 и предоставляет данные этим наблюдателям. 393 00:17:08,410 --> 00:17:11,930 Или, если один из наблюдателей был в фоне 394 00:17:11,930 --> 00:17:14,290 и зате снова стал видимым, то LiveData 395 00:17:14,290 --> 00:17:17,079 Позаботится о том, чтобы отправить последние данные. 396 00:17:17,079 --> 00:17:19,608 этому наблюдателю. 397 00:17:19,608 --> 00:17:22,858 И тогда мы сможем сделать наш LocationListener singleton объектом 398 00:17:22,858 --> 00:17:26,019 потому как мы не нуждаемся в нескольких экземплярах. 399 00:17:26,020 --> 00:17:30,400 Итак, если мы взглянем на LiveData, то это жизненный цикл знающий о наблюдателе. 400 00:17:30,400 --> 00:17:32,520 Это очень просто начать и остановить эти действия. 401 00:17:32,520 --> 00:17:34,650 Не важно как много у вас наблюдателей, 402 00:17:34,650 --> 00:17:39,740 или в каком они состоянии, вы сливаете их в один жизненный цикл. 403 00:17:39,740 --> 00:17:42,000 И этого нет ни в Activities, ни в Fragments 404 00:17:42,000 --> 00:17:44,620 внутри их, но это работает с любыми из них. 405 00:17:44,620 --> 00:17:47,460 И LiveData тестировалась, потому что 406 00:17:47,460 --> 00:17:49,080 Android открытая платформа. 407 00:17:49,080 --> 00:17:52,720 И если вы знакомы с печально известной FragmentTransaction 408 00:17:52,720 --> 00:17:56,670 exception, мы гарантируем вам, что наблюдатель никогда не будет, 409 00:17:56,670 --> 00:17:59,750 вызван в состоянии, когда вы не сможете запустить 410 00:17:59,750 --> 00:18:01,260 вашу FragmentTransaction. 411 00:18:01,260 --> 00:18:03,780 Итак, это очень и очень особенно разработанные средства 412 00:18:03,780 --> 00:18:08,100 для работы с вашими Activities и Fragments. 413 00:18:08,100 --> 00:18:11,520 OK, давайте поговорим о смене ориентации экрана. 414 00:18:11,520 --> 00:18:14,460 Ну, этот пример был легким т.к. местоположение является глобальным, 415 00:18:14,460 --> 00:18:17,550 Но в большинстве случаев, данные связаны с UI. 416 00:18:17,550 --> 00:18:22,770 Итак, если у нас есть Activity, где показывается профиль пользователя, 417 00:18:22,770 --> 00:18:24,660 и мы добавили веб-сервис который может вернуть 418 00:18:24,660 --> 00:18:28,260 данные как LiveData, которые мы можем безопасно 419 00:18:28,260 --> 00:18:32,580 наблюдать, не опасаясь утечки из Activity, 420 00:18:32,580 --> 00:18:33,470 это выглядит прекрасно. 421 00:18:33,470 --> 00:18:35,030 Мы никогда не упустим эту Activity, 422 00:18:35,030 --> 00:18:36,390 это будет работать очень хорошо. 423 00:18:36,390 --> 00:18:40,340 Исключая... Что случится если пользователь повернет устройство? 424 00:18:40,340 --> 00:18:42,850 Давайте взглянем на линию жизненного цикла снова. 425 00:18:42,850 --> 00:18:44,790 Итак, Activity создано, это запомнили, OK. 426 00:18:44,790 --> 00:18:46,752 Получаем пользователя. 427 00:18:46,752 --> 00:18:48,460 И пока мы получаем [проверяем accaunt] пользователя, 428 00:18:48,460 --> 00:18:51,390 пользователь решает поверну-ка я телефон. 429 00:18:51,390 --> 00:18:53,130 и тогда Activity разрушится. 430 00:18:53,130 --> 00:18:55,740 К счастью, мы не получили утечку, это здорово. 431 00:18:55,740 --> 00:18:57,810 Но когда наше новое Activity запустилось, 432 00:18:57,810 --> 00:18:59,620 делаем новый вызов. 433 00:18:59,620 --> 00:19:02,160 Ну, ничего страшного, но не айс. 434 00:19:02,160 --> 00:19:03,640 Чего мы хотим? 435 00:19:03,640 --> 00:19:05,700 Мы хотим реально удерживать эти данные, правильно? 436 00:19:05,700 --> 00:19:09,870 Мы уже отправляли это запрос, зачем отправлять его опять? 437 00:19:09,870 --> 00:19:12,780 Мы хотим, чтобы наш график выглядел так. 438 00:19:12,780 --> 00:19:14,640 Итак, если новая Activity появляется, нам следует 439 00:19:14,640 --> 00:19:18,330 быть способными вернуть ту же view model, которая и есть 440 00:19:18,330 --> 00:19:20,340 новый класс называемый ViewModel. 441 00:19:20,340 --> 00:19:22,290 Итак, мы представляем этот новый класс 442 00:19:22,290 --> 00:19:23,760 очень спецефичный для этой вещи, где 443 00:19:23,760 --> 00:19:27,210 вам следует поместить данные внутри вашей Activity 444 00:19:27,210 --> 00:19:30,940 во ViewModel, и сделать вашу Activity свободной от данных. 445 00:19:30,940 --> 00:19:33,000 Итак, если вы хотите изменить эту Activity, 446 00:19:33,000 --> 00:19:36,910 вы создаете этот новый класс, наследуемый от VewModel class. 447 00:19:36,910 --> 00:19:41,830 Независимо от того, какие данные были внутри Activity, мы помещаем их 448 00:19:41,830 --> 00:19:45,630 во ViewModel-класс, и там, все, что мы делаем, делаем внутри getUser(), 449 00:19:45,630 --> 00:19:48,790 если это первый запуск, получаем данные из веб-службы. 450 00:19:48,790 --> 00:19:51,800 Иначе, возвращаем текущее значение. 451 00:19:51,800 --> 00:19:53,220 Теперь, супер просто. 452 00:19:53,220 --> 00:19:55,800 И внутри нашей Activity мы избавляемся от всего этого кода. 453 00:19:55,800 --> 00:19:58,590 Мы говорим получить ViewModelProviders.of(this) 454 00:19:58,590 --> 00:20:01,620 В каждой Activity или Fragment'е есть ViewModelProvider 455 00:20:01,620 --> 00:20:04,680 который вы можете получить, и этот ViewModelProvider знает 456 00:20:04,680 --> 00:20:06,510 как предоставить вам ViewModel. 457 00:20:06,510 --> 00:20:08,880 Итак, когда вы вызываете get(MyViewModel), 458 00:20:08,880 --> 00:20:10,530 в самый первый раз вы делаете этот вызов, 459 00:20:10,530 --> 00:20:11,940 мы даем вам новое состояние. 460 00:20:11,940 --> 00:20:13,780 Когда вращение Activity завершилось, 461 00:20:13,780 --> 00:20:16,760 начинается переподключение к той же ViewModel. 462 00:20:16,760 --> 00:20:19,432 А затем и остального этого кода также. 463 00:20:19,432 --> 00:20:22,318 [АПЛОДИСМЕНТЫ] 464 00:20:22,318 --> 00:20:28,580 465 00:20:28,580 --> 00:20:31,060 Итак, если вы посмотрите на жизненный цикл, он выглядит так. 466 00:20:31,060 --> 00:20:32,040 Это то, чего мы хотели. 467 00:20:32,040 --> 00:20:35,800 Новая Activity запускается, затем переподключается. 468 00:20:35,800 --> 00:20:38,140 И когда новая Activity завершается, 469 00:20:38,140 --> 00:20:41,050 Например, когда нам нечего делать с этой Activity, 470 00:20:41,050 --> 00:20:42,580 и тогда мы идем и говорим ViewModel, 471 00:20:42,580 --> 00:20:44,350 что он больше не нужен. 472 00:20:44,350 --> 00:20:48,340 Это на самом деле единственный метод во ViewModel классе. 473 00:20:48,340 --> 00:20:49,570 Так что это очень просто. 474 00:20:49,570 --> 00:20:51,640 Поэтому, если мы посмотрим на жизненные циклы, они 475 00:20:51,640 --> 00:20:53,310 хранят данные для Activity. 476 00:20:53,310 --> 00:20:56,500 Они выживают при изменениях конфигурации. 477 00:20:56,500 --> 00:20:58,930 Они никогда не должны, каждый раз ссылаться на Views 478 00:20:58,930 --> 00:21:00,870 потому что они [НЕРАЗБОРЧИВО] покидают эти Activities. 479 00:21:00,870 --> 00:21:03,430 Итак, вы не можете ссылаться обратно на Activity. 480 00:21:03,430 --> 00:21:05,640 Вот почему вы используете такие вещи, как LiveData, 481 00:21:05,640 --> 00:21:08,550 Rx Java, или наблюдатели с хранением данных 482 00:21:08,550 --> 00:21:10,270 чтобы совершать эту коммуникацию. 483 00:21:10,270 --> 00:21:12,730 И это то, почему все наши разговоры про Activity - это всегда 484 00:21:12,730 --> 00:21:15,070 разговоры о ViewModel. 485 00:21:15,070 --> 00:21:19,210 Теперь еще одна большая тема о поддержке сохранности данных. 486 00:21:19,210 --> 00:21:22,000 Теперь мы знаем, написать хорошее, отзывчивое приложение на Android 487 00:21:22,000 --> 00:21:24,860 означает и то, что необходимо сохранять данные на диск. 488 00:21:24,860 --> 00:21:27,700 Если мы взглянем на Android, там есть 3-4 основных API для этого. 489 00:21:27,700 --> 00:21:29,980 Один из которых это ContentProvider, который 490 00:21:29,980 --> 00:21:32,320 переносит данные между процессами. 491 00:21:32,320 --> 00:21:35,530 В реальности это не имеет общего с сохранением данных. 492 00:21:35,530 --> 00:21:37,510 Другой способ это SharedPreferences, 493 00:21:37,510 --> 00:21:40,090 который сохраняет данные в XML. 494 00:21:40,090 --> 00:21:43,190 Вы можете сохранить только немного данных с его помощью. 495 00:21:43,190 --> 00:21:44,800 Последний способ это SQLite, которая 496 00:21:44,800 --> 00:21:48,160 была введена с версии Android 1. 497 00:21:48,160 --> 00:21:49,720 Итак, вы знаете, вам нужно использовать SQLite 498 00:21:49,720 --> 00:21:51,890 если вы хотите хранить много данных. 499 00:21:51,890 --> 00:21:55,330 Вы идете на developer.android.com/ это 500 00:21:55,330 --> 00:21:57,960 самое первое сохранение ваших данных. 501 00:21:57,960 --> 00:22:00,130 Это очень запутывает. 502 00:22:00,130 --> 00:22:01,642 Это очень грустно. 503 00:22:01,642 --> 00:22:03,370 [СМЕХ] 504 00:22:03,370 --> 00:22:06,190 Итак - OK, мы хотим сделать это менее грустным. 505 00:22:06,190 --> 00:22:07,960 Мы хотим сделать это приятным. 506 00:22:07,960 --> 00:22:10,060 Итак, посмотрим на пример, правильно? 507 00:22:10,060 --> 00:22:11,740 Так что - сверху, он пытается сказать, 508 00:22:11,740 --> 00:22:15,670 "Я хочу выбрать эти три столбца с таким-то условием, 509 00:22:15,670 --> 00:22:17,950 и я хочу отсортировать результат так-то." 510 00:22:17,950 --> 00:22:20,670 Это на самом деле, довольно простой SQL-запрос, 511 00:22:20,670 --> 00:22:22,210 но вам нужно написать весь этот код. 512 00:22:22,210 --> 00:22:24,160 Плюс, этот код даже не показывает где 513 00:22:24,160 --> 00:22:27,720 вы определяете все эти константы. 514 00:22:27,720 --> 00:22:29,430 Чего же мы хотим на самом деле? 515 00:22:29,430 --> 00:22:32,060 мы хотим избавиться от этого кода без шаблонов. 516 00:22:32,060 --> 00:22:34,890 Когда вы пишете на Java, если вы делаете опечатку в Java, 517 00:22:34,890 --> 00:22:36,630 он не компилирует код. 518 00:22:36,630 --> 00:22:39,010 Мы хотим похожую вещь для SQL. 519 00:22:39,010 --> 00:22:42,000 Мы все еще хотим использовать SQLite, потому что на каждом девайсе Android 520 00:22:42,000 --> 00:22:43,740 есть эта проверенная технология. 521 00:22:43,740 --> 00:22:46,230 Мы знаем, это отлично работает. 522 00:22:46,230 --> 00:22:48,280 Но мы хотим проверять компиляцию на лету. 523 00:22:48,280 --> 00:22:49,970 Поэтому мы не хотим код по шаблонам, 524 00:22:49,970 --> 00:22:52,480 мы хотим проверять компиляцию на лету, в реальном времени. 525 00:22:52,480 --> 00:22:56,220 Мы сказали "ОК - мы пришли с Room, которая является объектом 526 00:22:56,220 --> 00:22:59,649 mapping library для SQLite". [т.е. ORM] 527 00:22:59,649 --> 00:23:05,800 [АПЛОДИСМЕНТЫ] 528 00:23:05,800 --> 00:23:08,210 Если мы посмотрим на этот запрос, мы скажем, 529 00:23:08,210 --> 00:23:10,770 "OK, давайте поместим этот запрос под аннотацию. 530 00:23:10,770 --> 00:23:12,610 Мы любим аннотации". 531 00:23:12,610 --> 00:23:14,560 И у нас есть объект Feed, который 532 00:23:14,560 --> 00:23:16,360 мы хотим сохранить в базе данных. 533 00:23:16,360 --> 00:23:19,270 Я хочу поместить этот запрос внутри интерфейса. 534 00:23:19,270 --> 00:23:21,280 Вы хотите создать FeedDao - 535 00:23:21,280 --> 00:23:24,040 Dao означает Data Access Object. 536 00:23:24,040 --> 00:23:27,430 Обычно для баз данных, лучший способ разместить там данные 537 00:23:27,430 --> 00:23:29,350 это сделать это через абстракцию. 538 00:23:29,350 --> 00:23:32,252 Тогда, нам всего лишь нужно сказать Room "это DAO". 539 00:23:32,252 --> 00:23:34,360 Сказать Room: "это сущность". 540 00:23:34,360 --> 00:23:37,960 И наконец, у нас был класс базы данных, который говорил: 541 00:23:37,960 --> 00:23:41,050 "Что у меня есть сущности - поэтому есть несколько сущностей, 542 00:23:41,050 --> 00:23:45,240 и у меня есть данные для доступа к объектам, которые вы видели. 543 00:23:45,240 --> 00:23:46,210 Это все, что вы пишите. 544 00:23:46,210 --> 00:23:48,760 Как только вы напишите это, вы можете получить реализацию этого 545 00:23:48,760 --> 00:23:49,590 с помощью Room. 546 00:23:49,590 --> 00:23:52,750 Это очень похоже на то, когда вы используете Retrofit или Dagger - 547 00:23:52,750 --> 00:23:57,080 вы определяете интерфейсы, мы обеспечиваем реализацию. 548 00:23:57,080 --> 00:23:59,740 Теперь, как только мы узнали, что это DAO, мы можем 549 00:23:59,740 --> 00:24:01,210 использовать методы быстрого доступа. 550 00:24:01,210 --> 00:24:05,350 Такие как, insert() это, или deleteAll() это, or updateAll() - 551 00:24:05,350 --> 00:24:06,930 Куча методов бытрого доступа. 552 00:24:06,930 --> 00:24:08,710 Вы можете задавать множесто параметров. 553 00:24:08,710 --> 00:24:11,115 Так много, пока сможете читать. И это имеет смысл, 554 00:24:11,115 --> 00:24:13,930 Room поймет их. 555 00:24:13,930 --> 00:24:16,000 Но наиболее важная часть Room - это то, 556 00:24:16,000 --> 00:24:18,680 что он понимает ваш SQL. 557 00:24:18,680 --> 00:24:20,320 Итак часть - все те константы, о которых 558 00:24:20,320 --> 00:24:23,630 я упомянул, мы определили, чтобы избежать ошибок во время компиляции, 559 00:24:23,630 --> 00:24:26,560 Room реально дает это все бесплатно. 560 00:24:26,560 --> 00:24:28,380 Поэтому, когда Room видит этот запрос, то говорит: 561 00:24:28,380 --> 00:24:31,060 "ОК, вы получаете эти три столбца 562 00:24:31,060 --> 00:24:34,900 из этой таблицы, где название похоже на это ключевое слово. 563 00:24:34,900 --> 00:24:36,705 Откуда это ключевое слово? 564 00:24:36,705 --> 00:24:38,710 О, да оно приходит из параметров функции. 565 00:24:38,710 --> 00:24:39,567 Имеет смысл. 566 00:24:39,567 --> 00:24:40,900 И что она хочет вернуть? 567 00:24:40,900 --> 00:24:42,970 Она хочет вернуть список объектов Feed." 568 00:24:42,970 --> 00:24:45,330 И тогда Room идет и проверяет. 569 00:24:45,330 --> 00:24:47,980 "Подходят ли эти столбцы к объекту, который 570 00:24:47,980 --> 00:24:49,690 пользователь хочет вернуть?" 571 00:24:49,690 --> 00:24:53,812 И, как только они равны, говорится: "OK, я могу сгенерировать этот код." 572 00:24:53,812 --> 00:24:55,270 Вы можете даже, скажем, выбрать звездочку [все столбцы]. 573 00:24:55,270 --> 00:24:56,600 Вам не нужно их перечислять. 574 00:24:56,600 --> 00:25:00,190 Room реально, реально понимает ваш запрос. 575 00:25:00,190 --> 00:25:03,130 Вы можете даже соединить 10 таблиц, и это все еще будет работать. 576 00:25:03,130 --> 00:25:05,020 Но что, если вы сделали опечатку? 577 00:25:05,020 --> 00:25:07,750 Вместо того, чтобы написать "feed" вы пишите "feeds". 578 00:25:07,750 --> 00:25:10,750 Теперь, если это случится, Room собирается дать вам 579 00:25:10,750 --> 00:25:12,940 ошибку времени компиляции. 580 00:25:12,940 --> 00:25:15,040 Так что выходит, что ваш запрос проверяется 581 00:25:15,040 --> 00:25:17,080 по схеме, которую вы определили. 582 00:25:17,080 --> 00:25:19,562 И вам сообщается, если вы где-то ошиблись. 583 00:25:19,562 --> 00:25:22,508 [АПЛОДИСМЕНТЫ] 584 00:25:22,508 --> 00:25:27,797 585 00:25:27,797 --> 00:25:29,380 Но это не единственное, что Room делает. 586 00:25:29,380 --> 00:25:30,860 Итак, если вы скажите - 587 00:25:30,860 --> 00:25:34,070 если ваш запрос верен, вы хотите получить ID и title. 588 00:25:34,070 --> 00:25:35,870 Говорится: "Хорошо, это запрос, но вы 589 00:25:35,870 --> 00:25:37,350 хотите вернуть это как строку." 590 00:25:37,350 --> 00:25:40,460 И тогда Room отвечает: "ОК, ты возвращаешь две колонки, 591 00:25:40,460 --> 00:25:42,260 но у тебя есть только одна строка. 592 00:25:42,260 --> 00:25:43,320 Это не имеет смысла." 593 00:25:43,320 --> 00:25:46,800 И это обратно выдаст вам ошибку во время компиляции. 594 00:25:46,800 --> 00:25:49,220 И это действительно хороший способ исправить это в Room. 595 00:25:49,220 --> 00:25:51,095 Вы можете в принципе создать любой Java класс. 596 00:25:51,095 --> 00:25:52,580 Это не нужно аннотировать, 597 00:25:52,580 --> 00:25:55,170 Не надо говорить ничего специально об этом Pojo, 598 00:25:55,170 --> 00:25:57,080 просто сказать Room вернуть его. 599 00:25:57,080 --> 00:25:59,780 Пока какой-либо запрос возвращает то, что 600 00:25:59,780 --> 00:26:01,880 соответствует тому, что вы хотите вернуть, 601 00:26:01,880 --> 00:26:05,250 Room напишет этот код вместо вас. 602 00:26:05,250 --> 00:26:07,470 И теперь наблюдатели, которые очень важны, не так ли? 603 00:26:07,470 --> 00:26:09,390 Если у вас есть запрос, подобный этому, то вы 604 00:26:09,390 --> 00:26:11,460 показывая список Feed'ов, вы очевидно 605 00:26:11,460 --> 00:26:14,295 захотите получить уведомление, когда данные изменятся. 606 00:26:14,295 --> 00:26:17,842 И в Room, если вы хотите сделать это, вы можете 607 00:26:17,842 --> 00:26:19,290 сказать и сделать. Скажите, 608 00:26:19,290 --> 00:26:22,980 чтобы она вернул LiveData, и она сделает это для вас. 609 00:26:22,980 --> 00:26:26,400 Потому что она знает ваш запрос, знает, что на него влияет. 610 00:26:26,400 --> 00:26:29,520 Таким образом это поможет вам узнать, если запрос изменится. 611 00:26:29,520 --> 00:26:32,280 И это та часть, где все эти архитектурные компоненты 612 00:26:32,280 --> 00:26:33,750 прекрасно работают вместе. 613 00:26:33,750 --> 00:26:36,640 Room уже знает о LiveData. 614 00:26:36,640 --> 00:26:40,340 Итак ваша ViewModel, все, что вы можете написать - из данных, 615 00:26:40,340 --> 00:26:42,600 вызовите этот запрос, и это все он сделает. 616 00:26:42,600 --> 00:26:46,650 Всякий раз, когда данные меняются, ваш UI обновляется также. 617 00:26:46,650 --> 00:26:49,470 И это только тогда происходит когда ваш UI виден [visible] 618 00:26:49,470 --> 00:26:52,958 И последнее, но не менее важное, Room также поддерживает RxJava 2. 619 00:26:52,958 --> 00:26:55,448 [ОВАЦИИ] 620 00:26:55,448 --> 00:27:01,930 621 00:27:01,930 --> 00:27:04,390 OK, если сказать о Room в двух словах, 622 00:27:04,390 --> 00:27:06,730 Она пишет шаблонный код для вас [вместо вас]. 623 00:27:06,730 --> 00:27:08,050 И она полностью поддерживает SQLite. 624 00:27:08,050 --> 00:27:10,990 Вы можете все просто писать на SQLite, будет работать и так. 625 00:27:10,990 --> 00:27:14,070 Она проверяет ваши запросы во время компиляции. 626 00:27:14,070 --> 00:27:17,350 Это стимулирует лучшие практики, которые помогают вам 627 00:27:17,350 --> 00:27:19,480 с тестами, миграцией и. 628 00:27:19,480 --> 00:27:23,020 также наблюдателями, и все это прямо из коробки. 629 00:27:23,020 --> 00:27:28,000 OK, архитектура, наша последняя тема на сегодня. 630 00:27:28,000 --> 00:27:30,000 Итак, с чего мы начали, верно? 631 00:27:30,000 --> 00:27:31,860 И теперь вы, возможно, спросите себя: 632 00:27:31,860 --> 00:27:34,335 "Что изменилось в 2017 году, что вы вдруг 633 00:27:34,335 --> 00:27:36,930 заговорили про архитектуру?" 634 00:27:36,930 --> 00:27:38,740 Хорошо, реально ничего не изменилось. 635 00:27:38,740 --> 00:27:40,560 Мы говорим об этой теме много. 636 00:27:40,560 --> 00:27:44,460 Adam Powell и я вели много разговоров на эту тему. 637 00:27:44,460 --> 00:27:49,050 Этот разговор начался с 2010, который я наблюдаю как разработчик. 638 00:27:49,050 --> 00:27:51,630 И это та тема, которую мы вполне четко обсуждали. 639 00:27:51,630 --> 00:27:54,720 Но чего не хватало, так это четко определенной ссылки 640 00:27:54,720 --> 00:27:56,022 на архитектуру. 641 00:27:56,022 --> 00:27:57,480 И это то, что мы запускаем в эти дни. 642 00:27:57,480 --> 00:27:59,370 Если вы пройдете сегодня на developer.android.com, 643 00:27:59,370 --> 00:28:01,680 после нашей сессии, есть секция 644 00:28:01,680 --> 00:28:05,246 о том, как быть архитектором в Android приложении. 645 00:28:05,246 --> 00:28:08,697 [АПЛОДИСМЕНТЫ] 646 00:28:08,697 --> 00:28:13,640 647 00:28:13,640 --> 00:28:15,890 И, таким образом, это гид по архитектуре. 648 00:28:15,890 --> 00:28:17,780 Это не книга догматических правил. 649 00:28:17,780 --> 00:28:20,600 Мы верим, что это очень хороший путь, чтобы писать приложения, 650 00:28:20,600 --> 00:28:24,320 но вы не обязаны, следовать за нами строчка за строчкой. 651 00:28:24,320 --> 00:28:27,400 Поэтому я кратко остановлюсь на архитектуре, 652 00:28:27,400 --> 00:28:28,960 но если вы потеряетесь немного, не волнуйтесь. 653 00:28:28,960 --> 00:28:31,950 У нас есть вся документации на developer.аndroid.com 654 00:28:31,950 --> 00:28:34,264 с простыми примерами. 655 00:28:34,264 --> 00:28:35,680 Итак, мы считаем, что приложение состоит 656 00:28:35,680 --> 00:28:37,300 из четырех главных частей - 657 00:28:37,300 --> 00:28:41,680 это UI-контроллеры, ViewModels, хранилище данных, 658 00:28:41,680 --> 00:28:43,030 и источники данных. 659 00:28:43,030 --> 00:28:45,640 Давайте разберем это в деталях. 660 00:28:45,640 --> 00:28:47,980 UI-контроллеры это ваши Activities, 661 00:28:47,980 --> 00:28:51,100 Fragments, custom Views. 662 00:28:51,100 --> 00:28:52,750 У них действительно простые задачи. 663 00:28:52,750 --> 00:28:55,270 Они наблюдают за полями у ViewModel 664 00:28:55,270 --> 00:28:56,720 и обновляют себя. 665 00:28:56,720 --> 00:28:58,540 И они хотят больше ответственности. 666 00:28:58,540 --> 00:29:01,540 Всякий раз, когда пользователь совершает действие в UI, 667 00:29:01,540 --> 00:29:04,450 они понимают это действие, и сообщают о нем во ViewModel 668 00:29:04,450 --> 00:29:07,540 так, что становится понятно, что пользователь хотел сделать. 669 00:29:07,540 --> 00:29:10,390 Если мы посмотрим на ViewModel, то это та сущность, которая 670 00:29:10,390 --> 00:29:13,450 готовит данные для UI, 671 00:29:13,450 --> 00:29:14,480 и держит их. 672 00:29:14,480 --> 00:29:16,740 Это то, где данные для UI-интерфейса. 673 00:29:16,740 --> 00:29:20,050 ViewModel знает как получить эти данные. 674 00:29:20,050 --> 00:29:21,949 Обычно есть LiveData. 675 00:29:21,949 --> 00:29:23,740 Если вы используете RxJava, это наблюдение за данными, 676 00:29:23,740 --> 00:29:26,940 или сбор информации от наблюдений. 677 00:29:26,940 --> 00:29:28,830 Это помогает "пережить" изменения конфигурации. 678 00:29:28,830 --> 00:29:32,200 И это то, почему мы помещаем данные во ViewModels. 679 00:29:32,200 --> 00:29:33,680 И это также шлюз. 680 00:29:33,680 --> 00:29:37,040 И это тоже понятно т.к. ваш UI-контроллер, когда 681 00:29:37,040 --> 00:29:39,230 говорит с ViewModel, связывается с остальными 682 00:29:39,230 --> 00:29:42,690 частями приложения. 683 00:29:42,690 --> 00:29:44,360 И что же тогда репозиторий? 684 00:29:44,360 --> 00:29:47,100 ViewModel выполняет функцию хранилища данных 685 00:29:47,100 --> 00:29:48,920 для UI-контроллера, правильно? 686 00:29:48,920 --> 00:29:51,060 Репозиторий хранит их, в предсталении хранилища данных 687 00:29:51,060 --> 00:29:53,520 для всего вашего приложения. 688 00:29:53,520 --> 00:29:56,070 Таким образом, это полная модель данных для приложения, 689 00:29:56,070 --> 00:29:58,560 и он обеспечивает обмен [предоставление] данными через простые API 690 00:29:58,560 --> 00:30:00,210 для остальной части приложения. 691 00:30:00,210 --> 00:30:03,420 У вас может быть пользовательский репозиторий, где вы даете user-ID, 692 00:30:03,420 --> 00:30:06,000 И получаете LiveData о пользователе 693 00:30:06,000 --> 00:30:07,650 Откуда у него данные? 694 00:30:07,650 --> 00:30:10,260 Вы не должны заботиться, это работа репозитория. 695 00:30:10,260 --> 00:30:11,280 Но как он это делает? 696 00:30:11,280 --> 00:30:12,420 Он беседует с - 697 00:30:12,420 --> 00:30:15,920 выборкой, синхронизацией, глядя на базу данных, 698 00:30:15,920 --> 00:30:17,990 или общаясь через ваш Retrofit. 699 00:30:17,990 --> 00:30:20,770 Это работа репозитория. 700 00:30:20,770 --> 00:30:23,100 И последнее но не менее важное, у нас есть источники данных, 701 00:30:23,100 --> 00:30:25,020 наподобие ваших REST API клиентов. 702 00:30:25,020 --> 00:30:28,470 Вы можете использовать Retrofit, или у вас есть SQLite база. 703 00:30:28,470 --> 00:30:30,500 Вы можете использовать Room, или вы можете использовать 704 00:30:30,500 --> 00:30:32,460 GRAM, это не слишком важно. 705 00:30:32,460 --> 00:30:34,920 И вы можете говорить другим провайдерам контента 706 00:30:34,920 --> 00:30:36,390 из других процессов. 707 00:30:36,390 --> 00:30:39,090 Эти вещи мы называем источниками данных. 708 00:30:39,090 --> 00:30:41,940 И мы думаем, что все эти слои 709 00:30:41,940 --> 00:30:43,830 могут обнаруживать друг друга чтобы создавать 710 00:30:43,830 --> 00:30:45,630 проверки зависимостей в системе, которые мы будем 711 00:30:45,630 --> 00:30:47,370 использовать с помощью Dagger. 712 00:30:47,370 --> 00:30:49,800 Но мы также озознаем, что понимание ситуации зависимости 713 00:30:49,800 --> 00:30:51,810 не очень легко. 714 00:30:51,810 --> 00:30:55,560 Это более сложная тема, и иногда может быть излишней. 715 00:30:55,560 --> 00:30:57,750 И вы могли бы использовать Service Locator, если 716 00:30:57,750 --> 00:31:01,560 вы чувствуете себя более комфортно с ним. 717 00:31:01,560 --> 00:31:04,050 Итак, давайте вернемся к конкретному - 718 00:31:04,050 --> 00:31:06,700 пройдем через конкретный пример. 719 00:31:06,700 --> 00:31:10,110 Допустим, у нас есть UI, который показывает профиль пользователя, 720 00:31:10,110 --> 00:31:12,380 и у нас есть источник данных который - мы сохраняем 721 00:31:12,380 --> 00:31:16,080 данные в базе данных, также можем получить их через сеть. 722 00:31:16,080 --> 00:31:18,210 Как мы получаем эти две вещи? 723 00:31:18,210 --> 00:31:21,240 Хорошо, мы говорим, что сначала нужен репозиторий пользователя. 724 00:31:21,240 --> 00:31:23,880 Пользовательский репозиторий знает, что он должен проверять базу данных. 725 00:31:23,880 --> 00:31:25,680 Если там нет, то сделать веб-запрос. 726 00:31:25,680 --> 00:31:28,500 Или между тем, также попытаться запустить базу данных. 727 00:31:28,500 --> 00:31:30,750 Не имеет значения, как делать это, 728 00:31:30,750 --> 00:31:32,820 но он [репозиторий] знает, как создать LiveData 729 00:31:32,820 --> 00:31:36,780 пользователя или наблюдателя, все равно кого. 730 00:31:36,780 --> 00:31:38,430 И тогда нам нужна ViewModel, правильно, 731 00:31:38,430 --> 00:31:41,670 потому что данные для UI живут в ViewModel. 732 00:31:41,670 --> 00:31:44,220 Итак мы создаем ProfileViewModel, 733 00:31:44,220 --> 00:31:48,030 который "говорит" с репозиторием, чтобы получить эту информацию. 734 00:31:48,030 --> 00:31:50,850 А затем реальный фрагмент получает данные 735 00:31:50,850 --> 00:31:54,450 из ViewModel, так что, если фрагмент возвращается, 736 00:31:54,450 --> 00:31:57,270 то LiveData будет в ProfileViewModel. 737 00:31:57,270 --> 00:32:00,070 Но если фрагмент исчезает полностью, 738 00:32:00,070 --> 00:32:01,680 мы избавляемся от ViewModel, 739 00:32:01,680 --> 00:32:05,240 и данных, которые могут быть собраны сборщиком мусора. 740 00:32:05,240 --> 00:32:07,100 Теперь, вся эта абстракция, которую мы создали, 741 00:32:07,100 --> 00:32:10,640 если вы заметели, каждый отдельный компонент говорит только о том, что 742 00:32:10,640 --> 00:32:14,520 находится прямо под ним, что помогает масштабировать ваше приложение. 743 00:32:14,520 --> 00:32:16,340 И это также имеет огромную побочную выгоду, 744 00:32:16,340 --> 00:32:18,260 которая называется тестированием. 745 00:32:18,260 --> 00:32:19,230 Вы же тестируете, правильно? 746 00:32:19,230 --> 00:32:24,500 747 00:32:24,500 --> 00:32:26,210 Итак, скажем, вы хотите протестировать ваш UI. 748 00:32:26,210 --> 00:32:27,880 Сейчас люди говорят UI- тестирование сложное. 749 00:32:27,880 --> 00:32:30,990 UI-тестирование - да, это сложно. 750 00:32:30,990 --> 00:32:33,320 Но часто это сложно потому, что вы пишете много кода 751 00:32:33,320 --> 00:32:35,290 внутри Activity. 752 00:32:35,290 --> 00:32:38,630 Теперь мы говорим, пиши больше во ViewModel, 753 00:32:38,630 --> 00:32:41,510 и вы знаете, что UI только говорит к ViewModel, 754 00:32:41,510 --> 00:32:43,520 так что вы можете избавиться от двух остальных [частей архитектуры]. 755 00:32:43,520 --> 00:32:47,170 Вам только нужно создать фальшивку ViewModel для тестирование вашего UI. 756 00:32:47,170 --> 00:32:50,900 Тестирование вашего UI становится супер, супер easy with Espresso. 757 00:32:50,900 --> 00:32:52,880 И у нас есть пример приложения на GitHub 758 00:32:52,880 --> 00:32:56,346 где вы можете проверить с [НЕРАЗБОРЧИВО]. 759 00:32:56,346 --> 00:32:58,220 И то же самое, что и для ViewModels. 760 00:32:58,220 --> 00:32:59,660 Если вы хотите протестировать ViewModel, 761 00:32:59,660 --> 00:33:02,330 вы знаете, что это только переговоры к репозиторию. 762 00:33:02,330 --> 00:33:05,860 вы заменяете его mock- репозиторием, и все работает. 763 00:33:05,860 --> 00:33:08,570 И вы даже можете тестировать ваши ViewModels 764 00:33:08,570 --> 00:33:11,150 на вашей главной машине, на JVM. 765 00:33:11,150 --> 00:33:12,780 И последнее, но не менее важное, вы можете тестировать 766 00:33:12,780 --> 00:33:14,030 репозиторий таким же способом. 767 00:33:14,030 --> 00:33:16,040 Вам нужен mock-источник данных. 768 00:33:16,040 --> 00:33:21,000 Вы можете легко протестировать свой репозиторий как JUnit тест. 769 00:33:21,000 --> 00:33:23,060 Я пониманию, что дал вам много информации. 770 00:33:23,060 --> 00:33:26,420 У нас будет две сессии завтра, и есть документация. 771 00:33:26,420 --> 00:33:29,630 Но теперь я хочу пригласить нашего product-manager LUKAS 772 00:33:29,630 --> 00:33:32,646 рассказать, что будет дальше. 773 00:33:32,646 --> 00:33:35,574 [АПЛОДИСМЕНТЫ] 774 00:33:35,574 --> 00:33:41,425 775 00:33:41,425 --> 00:33:42,800 LUKAS BERGSTROM: Как Yigit сказал, 776 00:33:42,800 --> 00:33:44,870 мы только много прошлись по поверхности. 777 00:33:44,870 --> 00:33:46,820 Но реально, мы скрыли много деталей 778 00:33:46,820 --> 00:33:48,080 пока мы рассказывали это. 779 00:33:48,080 --> 00:33:50,420 Но, к счастью, вам не нужно запоминать все, 780 00:33:50,420 --> 00:33:51,950 что вы теперь услышали. 781 00:33:51,950 --> 00:33:56,180 У нас много материала для вас на 782 00:33:56,180 --> 00:33:58,910 developer.android.com/arch. 783 00:33:58,910 --> 00:34:03,305 И эта ссылка должна работать через 21 минуту. 784 00:34:03,305 --> 00:34:06,260 785 00:34:06,260 --> 00:34:07,790 Мы хотели дать вам, ребята, шанс сделать заметку 786 00:34:07,790 --> 00:34:10,219 в блоге или твитнуть об этом раньше кого-нибудь еще. 787 00:34:10,219 --> 00:34:13,190 Вот почему мы придержали это. 788 00:34:13,190 --> 00:34:15,560 Итак, да, мы сделали хорошую документацию 789 00:34:15,560 --> 00:34:18,469 и она обозначает приоритеты для начала этого проекта, поскольку 790 00:34:18,469 --> 00:34:22,310 предоставление хорошего руководства одна из гланым наших задач. 791 00:34:22,310 --> 00:34:24,800 Итак, вы собираетесь найти углубленную документацию 792 00:34:24,800 --> 00:34:27,337 написанную с точки зрения разработчика. 793 00:34:27,337 --> 00:34:29,420 Вы действительно найдете содержательные примеры приложений 794 00:34:29,420 --> 00:34:31,280 и они покажут как создавать реальное. 795 00:34:31,280 --> 00:34:34,650 И как пример того, как много работы пошло на это, 796 00:34:34,650 --> 00:34:36,139 у нас есть GitHub пример приложения браузера, который 797 00:34:36,139 --> 00:34:39,440 вероятно имеет лучшее покрытие для тестирования, чем большинство 798 00:34:39,440 --> 00:34:42,170 приложений, написанных этим парнем. 799 00:34:42,170 --> 00:34:44,820 800 00:34:44,820 --> 00:34:47,420 И, конечно, у нас есть гид по архитектуре приложений, 801 00:34:47,420 --> 00:34:50,929 который внутри мы назвали гид на время. 802 00:34:50,929 --> 00:34:53,210 И считаем, что метка все еще применяется. 803 00:34:53,210 --> 00:34:55,639 Но даже, если вы не планируете, использовать ваши рекомендации 804 00:34:55,639 --> 00:34:58,580 по архитектуре, мы считаем вам следует посмотреть этот гид. 805 00:34:58,580 --> 00:35:04,010 Там есть принципы, которые мы думаем применимы ко всем приложениям. 806 00:35:04,010 --> 00:35:07,760 И вы, вероятно, спросите себя сделал я не - 807 00:35:07,760 --> 00:35:09,830 какое влияние это должно оказывать на меня? 808 00:35:09,830 --> 00:35:13,160 Должен ли я поменять способ, которым я все делаю? 809 00:35:13,160 --> 00:35:15,315 Вы знаете, если вы находитесь в запуске нового проекта, 810 00:35:15,315 --> 00:35:16,940 или у вас есть существующее приложение, но вы 811 00:35:16,940 --> 00:35:19,190 хотите улучшить его архитектуру, 812 00:35:19,190 --> 00:35:22,100 тогда мы рекомендуем взглянуть на этот материал. 813 00:35:22,100 --> 00:35:24,050 Это по-прежнему превью. 814 00:35:24,050 --> 00:35:26,790 Мы не будем бить версию 1.0 несколько месяцев, 815 00:35:26,790 --> 00:35:30,050 Но мы думаем, что это готовое для вас, ребята, 816 00:35:30,050 --> 00:35:32,460 руководство, чтобы проверить и использовать в своих проверках. 817 00:35:32,460 --> 00:35:34,250 Но, если вы счастливы с тем, что у вас есть, 818 00:35:34,250 --> 00:35:37,360 вам не нужно переписывать ваше приложение. 819 00:35:37,360 --> 00:35:39,530 Поэтому быть вместе в одном духе, это не значит, 820 00:35:39,530 --> 00:35:41,890 что мы диктуем всем, как поступать. Если 821 00:35:41,890 --> 00:35:44,590 вы довольны своей архитектурой, то вам следует ее сохранить. 822 00:35:44,590 --> 00:35:46,510 Если вы довольны вашей существующей ORM, 823 00:35:46,510 --> 00:35:48,820 вам не надо использовать Room. 824 00:35:48,820 --> 00:35:51,910 Архитектурные компоненты нужны для удобной совместной работы, 825 00:35:51,910 --> 00:35:55,780 Но они действительно работают отлично и сами по себе, отдельно. 826 00:35:55,780 --> 00:35:58,300 И смешивание и сопоставление применяется не только 827 00:35:58,300 --> 00:36:04,730 к архитектурным компонентам, но и к сторонним библиотекам. 828 00:36:04,730 --> 00:36:11,760 Итак - я жду, чтобы этот слайд появился.. 829 00:36:11,760 --> 00:36:14,389 Итак, вы можете использовать, что у вас есть, 830 00:36:14,389 --> 00:36:16,680 и начинать интегрировать архитектурные компоненты, где 831 00:36:16,680 --> 00:36:18,310 это имеет смысл. 832 00:36:18,310 --> 00:36:21,000 Итак, например, если вы счастливы с RxJava, 833 00:36:21,000 --> 00:36:24,510 но вам реально нравятся Lifecycle-зависимые компоненты 834 00:36:24,510 --> 00:36:27,360 которые Yigit только что показывал, у вас есть эти самодовлеющие 835 00:36:27,360 --> 00:36:31,590 компоненты, вы можете использовать LiveData совместно с RxJava. 836 00:36:31,590 --> 00:36:34,800 Итак, вы можете получить все преимущества от RxJava действий, 837 00:36:34,800 --> 00:36:36,420 и теперь это будет Lifecycle-безопасно. 838 00:36:36,420 --> 00:36:39,510 Так что, наподобие лучшего из обоих миров. 839 00:36:39,510 --> 00:36:41,760 И у нас есть дополнительная инфа про интеграцию. 840 00:36:41,760 --> 00:36:45,890 Мы определенно смотрим на много вещей внутри 841 00:36:45,890 --> 00:36:48,480 и это было бы неплохо, если бы они были самодостаточны 842 00:36:48,480 --> 00:36:50,500 и Lifecycle-зависимы. 843 00:36:50,500 --> 00:36:53,460 И если вы разработчик библиотеки, 844 00:36:53,460 --> 00:36:55,920 мы настоятельно рекомендуем проверять жизненные циклы 845 00:36:55,920 --> 00:36:57,690 и LifecycleObserver потому что мы думаем 846 00:36:57,690 --> 00:37:00,480 это реально яркое будущее и есть много потенциала 847 00:37:00,480 --> 00:37:03,420 в создании библиотечных компонентов, которые зависимы от жизненного 848 00:37:03,420 --> 00:37:07,870 цикла по умолчанию. Но перед тем как сделать 849 00:37:07,870 --> 00:37:11,110 это, у нас есть еще много для вас на I/O в этом году. 850 00:37:11,110 --> 00:37:15,310 У нас есть еще две беседы, одна про жизненные циклы 851 00:37:15,310 --> 00:37:18,280 это даже более глубоко, чем что мы покажем завтра 852 00:37:18,280 --> 00:37:20,020 утром. 853 00:37:20,020 --> 00:37:24,040 У нас есть еще Room и поддержка сохранности данных 854 00:37:24,040 --> 00:37:25,480 немного раньше чем о Room 855 00:37:25,480 --> 00:37:27,790 начнется в 12:30 завтра. 856 00:37:27,790 --> 00:37:31,950 И у нас будут люди, которые хороше кумекают в архитектурных 857 00:37:31,950 --> 00:37:36,740 компонентах на песочнице для всех на I/O. 858 00:37:36,740 --> 00:37:41,600 И у нас есть codelabs, которыми мы очень довольны. 859 00:37:41,600 --> 00:37:43,890 И еще все впереди. 860 00:37:43,890 --> 00:37:46,100 Поэтому мы думаем, что мы только слегка затронули области, 861 00:37:46,100 --> 00:37:48,260 с помощью которых мы можем улучшить использование Android 862 00:37:48,260 --> 00:37:51,320 фреймворка, и мы также рассматриваем применение этого подхода 863 00:37:51,320 --> 00:37:53,310 в других областях. 864 00:37:53,310 --> 00:37:54,980 Итак, некоторые вещи уже работают. 865 00:37:54,980 --> 00:37:58,310 И мы также заинтересованы слышать от вас, о том, 866 00:37:58,310 --> 00:37:59,720 чтобы вы хотели еще видеть. 867 00:37:59,720 --> 00:38:04,010 Так что приходите, говорите с нами, что вам нравится, чего вам нехватает. 868 00:38:04,010 --> 00:38:06,800 И следите за обновлениями, которые мы реально ждем от будущего 869 00:38:06,800 --> 00:38:08,570 Android разработки. 870 00:38:08,570 --> 00:38:09,310 Спасибо. 871 00:38:09,310 --> 00:38:11,460 [АПЛОДИСМЕНТЫ] 872 00:38:11,460 --> 00:00:00,000 |
20 08 2017