LiveData with Coroutines and Flow (Android Dev Summit '19)

[Music] hi there mine my name is Joseph Erica I'm a developer relations engineer working on Android my name is Zee boy I also work on the Android team and today we're going to talk about live data again we're here last year with a talk title fun with live data today we're going to talk about its integration with coroutines and with Flo so since API with struggle to understand life's androids life cycles we've all studied the diagrams and more diagrams and then fragments came along and generated more diagrams so you know we Android developers try to isolate ourselves from having to deal with this problem we created a layer architecture in which only the presentation layer would know about the lifecycle and then even inside the presentation layer we found some some patterns and some rules that work well like for example having an object that would survive an activity or a fragment recreation we use this idea in the view model class in architecture components so let's look at that animation a little bit more in detail so a view is created and a view model is obtained so it's created as well it exposes one or multiple like data and then the view subscribes to these live data via data binding or manual subscription then there's a configuration change rotation for example the view is destroyed and a new instance of the view appears it subscribes again to the live data and the view model doesn't know what just happened the view model doesn't even have a reference to the view is it just exposes data so why are we talking about this whenever you do an operation and an operation can be something like fetching data from the network preparing some text you have to choose the scope of this operation this means when this operation is going to cancel if you cancel too late then you might be wasting the use of resources if you cancel it too soon you might have to restart your operation but in a real world app and this is the Android they have some it up we have way more scopes than that for example we have a schedule screen with multiple potentially multiple instances of the fragment schedule the view model that is scoped to the screen the agenda the info screen with fragments and B model as well then we have a main activity and a view model that is scoped to these activity and then you can even have custom scopes with the navigation component for example you can create a scope for a login flow or for a check-up flow and then we even have the application scope which which is a special case we'll talk about later so there's going to be a lot of operations happening at the same time and we have to manage the cancellation somehow somehow we need a way to find something that helps us structure this concurrency what would that be this of course our new best friend coupling Cortese now we don't want to go through and make an introduction the Kotlin Cortese but we want to talk about why we like it for this particular use case of Android what briefly there like three main nice things first one is it's very easy to get off the main thread like this a problem we tried to solve it like 20 different technologies Oviatt with Cortese you just launched it and now you can change your dispatcher it's very easy to write and while writing that you don't need to write boilerplate code this probably the best thing about Copeland qualities you write it as if you are writing it like blocking code and then it's all compiler magic and becomes a synchronous but these two are nice properties but they're not the reasons why we like coatings for this case the main reason is the structured concurrency it provides is that a bit complicated but basically you can consider structure concurrency as a garbage collector for your jobs so when something doesn't need to run anymore it is killed for you automatically and this is why we like it so if you like qualities of and how do you launch them luckily in the jetpack components we provide scopes for related Android components so for example if you're in a view model and you wanna run something in the scope of a view model there's a view model scope you can use it to launch your qualities or if you're in an activity or a fragment you can use the lifecycle scope which gets cancelled if the life cycle is destroyed now in this life cycle case there is one more thing sometimes you want to run certain operations when the life cycle is started like a fragment transaction for those cases you can use this launch when started resume or created matters what this does is it runs your husband blog only when the life cycle is in the desired State or greater and if you'd let's say you said large fan started and the activity stopped we suspend that computation until the activity resumes now the third layer is your application layer where things get a little bit more trickier like assume you wanna run something that's not tied to any screen in those cases you need to figure out whether you should be using web manager or not and the question you ask is does this thing has to complete like if you're writing a Twitter client and you need to send it to your server please use word manager because if you lose that to it that would be a shame but if you're trying to do something where you're going to clean the local database it's fine you can use the application scope like if that doesn't complete it's not the end of the world you can do next time the application starts now let's look at how we can use that via model scope with a live data here we have a common pattern you have a private mutable live data that you provide as a public property to do your UI inside here we launched our remodeled scope we do some suspending computation and when the result comes we update our private me to a live data and notice that I'm just setting the value that I'm not calling post value because this runs on the main dispatcher by default since lifecycles 2.

0 there is a much nicer way to do that pattern which is a new builder called live data this live data builder gives Corie team block which is like a scope for your live data its thus executing when the lies data is observed and canceled man by data is not used anymore and inside that you can emit another very common pattern is like imagine you have a UI right like users select some item and then you display the contents of that a wear common way to do is that you keep that item ID in a mutable live data run a switch map transformation on it and again for these cases you can use this live data builder and just do a quality in computation that this like that a builder also receives a quality in context so you can tell it to maybe run on the oil by default and it doesn't matter you can still call Emmy so you don't need to think about which thread or with this picture a man you can always call em it there's one more function called emit source which receives a live data this basically says whatever this other live data dispatches send them as my value so how do we cancel them alright so how do you cancel a local routine well I'm not here to talk about how to actually cancel a 13 that you just started we've been talking about scoping our curtains so that this is done automatically for us there's some use cases for this but normally you won't be cancelling your own your own jobs what I want to point out here is what happens if you are designing a suspend function and that function for example has an infinite loop how does Copley know when to stop that loop well turns out there's a little bit of magic here also spending functions in code linux quarantines are cancelable and delay is one of them so when delay is called it's going to check if the coroutine is canceled and if it is it's going to stop the execution so what happens if you're not calling any cancelable functions in your suspend function well you have to cooperate we say that cancellation is cooperative you have to check if the if the curtain is active regularly with the is active property so before we see some buttons there's an important distinction that we have to to make and that's between one-shot operations and operations that are going to return multiple values over time and we're going to see this with an example from the Twitter app so in order to load this the data needed for this screen you have to perform some one-shot operations downloading the profile picture the Twitter handle the tweet itself because tweets are not editable in 2019 Mike but there's another thing there's an interesting thing at the bottom number of retweets a number of likes this UI is observing a data source because if you keep this screen open those numbers are going to change over time so that's the difference so how does a one-shot operation look like in the big picture we use like data between vo and B model for the reasons that I explained in the introduction and then in the view model we're going to make this bridge between the live data world and the curtains world using the live data accrue team builder super easy in the repository because we are in suspend functions we can just call suspend functions in the data source we get a result we've done when you have when we have to deal with multiple values things get complicated and we solve this we can solve this with live data we can use live data beyond the view model and our talk last year was partly about this but live data was never designed as a fully fledged reactive stream builder so it's a little bit awkward to use so luckily there's a new API called flow flow is part of coddling Cortines and we're going to see some examples of some some code examples and we're going to look at view model repository and data source so first we're going to see some view model patterns we're going to compare two view models side-by-side one is going to subscribe to a live data or consume data from a live data and the other one is going to consume from a flow so the first button is a in meeting multiple values if we're not doing any transformations to the values then we just can't we can just assign a live data that we're observing to the live data that we are exposing that's very easy in the case of flow we need to convert from a flow to live data somehow so we could use the live data a routine builder so we collect each item from the flow that's how you consume a flow and then we emit to the live data curtain Builder every item now this is more or less readable but if you have to do this 15 times in your view model it's going to be a lot of boilerplate so we created this handy just like data extension function that is going to convert any flow to live data and we're going to use it in the rest of the examples the next pattern is emitting one initial value and then emitting multiple ones so we already saw this pattern we use emit and a mid source from the live data core team builder in flow we could use the same pattern and we pass the flow converted to live data with a slag data but this is not very readable and well it's super-awkward and we're creating a live data twice so it's much better if we embrace flow a flow API and we use this thing called onstart that is going to let us define what the initial value of that flow is and then at the end we just convert to like data and this is where flow really shines normally you want to do a transformation on each item that you are observing or that you are receiving and if we do this with live data then you might want to try map first but this would be main threat and it would be awkward to use co-routine from here so it's much better that we use switch map and we return live data traded with a builder and because we are in a quarantine context we can call this heavy transformation function which would be a suspend function and I mean it's result with flow this is much much better we just call map on the flow and because we are inaccurate in context we can call the suspend function at the end we just convert to live data all right so how do we use the suspend functions and flow library in our repositories now reporter is usually where you have a lot of custom code like you're making API is collecting data filtering whatever business so you have in these cases you may want to do a lot of transformations and I suppose as I mentioned like we never intended live data to do these things luckily with flow it you have all these operators on your streams that you can use so just go ahead and use flow or saucepan functions in repositories similarly for your data sources suspend functions and flow are great feet but here things get a little bit more trickier because this is usually the part of your code where you're talking to other libraries remote sources Magne so you don't control all of it so let's look at all those cases see how we can integrate them the first case the best case is you have one shut operation so you have one shot operation to get some value like they say from a network request so if you're using retrofit just mark the function as suspending you are done retrofit already support saucepan function sees version 2.

6 similarly if you're using blue for your database since version 2.

1 it's supposed a swap function so you tell it to turn Sussman's function done you don't need to care about anymore but if you're dealing with a library that's not updated for the court use world maybe the Java library and it has callbacks some super old corvex you know you need to do some work for those cases we have this thing called husband casts over Cora team builder this thing is basically the adapter between the quartey's world and the callback based world what you do is when you call this function it gives you a continuation that you are responsible to call so we make our API request if the API gives us a value we resume the continuation or if the API tells that an error happened we resume the continuation with an exception this all you have to do once you do this rest of the quality missionary works and you can abstract this somewhere outside of your code notice that if you happen to call this continuation much later like after this castle is just ignored it grows a change is called a little bit better so that if the court is cancelled you can eat is eagerly castle your API request now the third case is value have out of values that you want to omit multiple values and for builder is a grating is very similar to the live data builder except you will the floor and you can emit values so we have an example here that like infinitely every two seconds this base is any weather value it's also super handy when you're writing test section you just like to say this is this other flow but if you are working with an old library again that doesn't support flow and like is a callback you can use this callback flow of builders it's very similar to the previous one we saw so let's say we have an imaginary API here that receives an imaginary callback and that callback has three functions so next value on error and uncompleted we register that callback with our imaginary API and every time we receive one of those callbacks we just say ok offer that value if an email came offer it to the floor or an error happens basically close the fall with this error or if it closes and I see same way close the flow now you need to be careful here because this callback flow builder once it returns for is closed so you cannot dispatch value Street anywhere we don't want it to return so for those cases we have this thing called function called irate calls which basically suspense until the fall is not to collect it anymore there might be any reason you closed here or maybe the collector just stopped collecting and in that case we simply unregistered from our API now testing so we would like to talk about testing but we don't have that much time no no less well we HIPAA testing is important so we have a full fledge telecom testing by Sean and Manny tomorrow at 5:15 please go watch nothing likes to see how you can effectively use qualities in your tests before we leave there is one more thing with the introduction of flow and the life cycles cause we shown you can actually get the benefits of live data without using live data so if your group you could be doing this where you say lifecycle scope launch event started and start collecting on this flow this will behave exactly the same way and live data behaves for your UI now it's not 100% the same thing because live data has this caching behavior but it's close to there so it says something you may want to consider and for any questions we'll be upstairs for the Queenie thank you [Music].

Hãy bình luận đầu tiên

Để lại một phản hồi

Thư điện tử của bạn sẽ không được hiện thị công khai.


*