How to Survive the lifecycle
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Joecks, Simon
The new view Lifecycle Owner introduces the third dedicated lifecycle into architecture components. In the session, Simon Joecks will show how to use it and will discuss its consequences for your view-model.
 Hello. Hello, everyone. My name is Simon Yerkes and I'm working at here Technologies. And today I'm going to talk a little bit about how to survive the life cycle. And this is mainly around the architecture components and how we actually deal with the certain kind of life cycles that they are now introduced to us. And for this I'm going to do a little bit of a short introduction to this kind of, let's say objects, you could say. So in general, everybody is more or less aware of the architecture components. Raise your hand if you have heard of it. I think everybody knows nowadays about this. I just give a very short recap, like two, three minutes, just to be really on the same page. Because some of the things that I'm going to talk about later are going to have to have some recap, basically. So first of all, the life cycle. The life cycle is basically just an object that was introduced to hold the state of activity or fragment. And basically represent, not hold, but represent the state of activity or fragment and give you the opportunity to be notified about it. So this sounds simple, but it is actually something that changed a lot in the architecture or in writing good applications. Because now you can actually make some guarantees and you can also subtract certain kind of aspects from your application that should never touch an activity or a fragment. Also a very interesting part of this is that the life cycle is actually provided by a certain kind of guarantee. So the steps here, like on create, on start, they are always basically called in the same kind of order. And building on top of this is way better now because previously in the different versions you had some issues with this kind of ordering. As a second object that we just recap quickly, we have the life cycle owner. I'm going to talk a little bit about more life cycle owners later. And it's basically just an object that holds a life cycle. And so you could build your own life cycle owner if you need to, if you want to build your own UI framework. And last but not least, in this kind of three important objects is the life cycle observer. And the life cycle observer is helping us to actually realize when something happened, when something changed within the life cycle. And here I took the Android X life cycle, a library, and there you have some new kind of servers. Like for instance, the full life cycle observer, which is a really nice different implementation than using the annotations, which is a little bit less efficient. I hope you already started to use Android X. Nobody? Well, it's pretty fresh, right? So on top of this, Google in the IO 2017 introduced a very useful object that is called the life data object. And this is just basically an emitter observer pattern where you can hold an object and it's going to react on your life cycle. And this sounds very simple, but it's actually changed a lot, at least in our architecture, on how we build applications. Because now you don't care about the life cycle anymore, you're basically just emitting data, you're producing it, and whenever anything happening through the life cycle, you just get informed correctly. Very important here to mention it, that it starts to emit data when it's fresh, when you come actually in the life cycle on start, and it's going to automatically remove all the observers in on destroy. And we're going to come to this point in a second because it's actually important to realize this. Last but not least is a concept that's the view model that is basically holding everything together across activities of fragments when they are destroyed. And this is the view model. The view model is nothing more than basically kind of a retained state where you can add a life data object or any kind of other objects that are going to be hold across basically the life cycle of your, of an activity or fragment. So with this three, five simple classes, you can actually do really, really cool stuff. But how do you actually bring everything together? So first of all, from Android X on, we have those kind of life cycles built in, and also with the appcompens 26, I think. You get all of these life cycle objects basically built into the standard libraries, and there are three of them that you should realize. And I'm going to talk about the last one in a second, and the first two are basically the fragment life cycle owner, sorry, the fragment activity life cycle owner, and then the other one is the fragment life cycle owner, and the new one that is introduced now with the, and the Google I owe 2018 is the view life cycle owner. And that's a particular one because it's a little bit different. It's not totally intuitive what it is doing and why is it there? Who have you heard actually of the view life cycle owner? Okay, just a few hands raised. So this is good because I think this talks mainly about putting awareness on this new object. Okay, so how does it work? So this is just a general recap, and maybe you're realizing the style a little bit because I copied it from the Google I owe slides more or less. So on the top, you can actually see the view model that holds some kind of data in life data object, and it's going to emit something, and this something is going to eventually be drawn on the fragment. But the fragment first needs to go through some kind of cycle, and the cycle starts with on create. So this is just a normal call, a normal life cycle method. At this point, we're going to actually register because the nice thing about those kind of life cycle methods you can just do everything in one method and in the on create method in this case. We start to observe, but at this point we are not getting actually this kind of value delivered right away, but we kind of have to wait until we are notified to be on start. On start at this point it's actually safe to draw anything on the screen and changing basically the view. And then we actually get delivered this kind of object and we can do something about it. Interesting is then if we are moving towards like if we're rotating for instance a fragment, then we are actually going to of course we get the on stop event and we are marking our observer as inactive. At this point we will not deliver any kind of further update anymore. So this means any object B that you can see here on the right is not actually going to be delivered and it's also going to be marked internally as not delivered to this particular observer, which is an important aspect. So then the fragment is going to be destroyed, all the resources going to be removed, and then eventually also the observer is going to out remove itself. So no more boilerplate code to just go on destroy and unregister your observer. It's a very, very clean setup basically. And in our applications actually it helped us a lot to have a very, very simple way to describe what is happening in your application. So what is happening next? We have the rotation case. So once you rotate the fragment, a new fragment is going to be created. We go through the same stages. On create it's going to be called we start observing again. And then we're going to go through on start and on start. We got actually the value that was not delivered previously is now delivered freshly to us. And so from there on we can actually draw the updated value. So you can realize that it's basically a very simple concept, but it actually helps a lot to build anything that is going asynchronous and anything that shouldn't be bound to the view. Who of you is actually aware of this kind of life cycle and understood it already previously? Okay, that's nice. Perfectly. Then I hope you're going to have a little bit more input on the or fun on the next part. So this helped us actually to do simple setups like this. So you have basically in on create on the fragment, you could actually just get the view model. And then from the view model, you would basically just observe the, you would just observe the with the fragments life cycle. You would observe the changes on the view model and then you get actually delivered this object B. Who of you knows actually that there's something wrong about this or problematic? Just a few hands. So who of you is using this kind of construct? Okay. Not too many actually. So I'm surprised. Okay. So what is problematic about this? So if we are not talking about the case of rotation where fragment is going to be destroyed, but we're talking of the case when we actually moving from one fragment to another in a fragment manager. So like a backstack case, you're moving like from one fragment to another and then you go back to your previous one. So few of you might know that at this point we are actually keeping the fragment in the memory, but something else is happening. So first of all, let's go for the same cases. So we have the life data object that is going to emit the object A. We go through on start and we're going to draw this again on the fragment. Then we are actually moving to the other fragment. At this particular point we are keeping the current fragment actually in the fragment manager. We just call on stop. Then we're going to detach the fragment from the view and we're going to start the other fragment. The other fragment is started at this particular point and it's going to do its magic, whatever we need to do that, and then we eventually press back. When we press back, the previous fragment is going to be reattached. Then it's going to its own cycle again, it's going to call on start, on start is going to happen, and then we mark our fragment as active again. Who of you sees an issue with this? Because we have had the same observer as previously, we actually marked A as already delivered. But what happened in detach and attach again is that we actually destroyed the view. There's a brand new view at this particular moment when we reattach the fragment. This view doesn't know anything about A. What you're going to show at this particular moment is an outdated view. This is a problematic issue. You can solve this issue with two kinds of ways. One way would be to actually tell the view to render this object A again. You can just call this clattery setup, which is making your app very ugly. Basically calling an onCreate, they change the view method that is basically going to be used again on view created, where we basically check if we have actually a value and then we call it again to basically redraw it. At this point you're basically saying if you are on the same page like the object A. Another setup many developers are using is actually this. This is also what our application has used a couple of weeks ago until I actually fixed and removed the bug that is coming from this. We actually would, on view created, we would listen to the observer. We are fine because it's a new view and then we get also a new observer. At this particular point we would always be notified when any object was changed with this observer. The problem with this is that we are still using the fragment lifecycle. The fragment lifecycle is not destroyed because we are keeping it in a memory. When we are coming back we would call this method a second time. Of course, can you imagine what happens at this particular time? We will create a second observer and suddenly we have two observers. We also keep actually, we can keep a reference to the previous view and by that leaking memory. A way to solve this problem is to call and on destroy view, remove the previous observer. This was a fix but you can see it clatters your code a lot. Especially if you have a lot of life data objects that you want to listen to, you're going to have a lot of this kind of boilerplate code. Of course, this is jeopardizing the whole idea actually on how to use life data and the lifecycle correctly. In the Google I O 2018 they realized we have to dedicate a certain kind of lifecycle for this. This is the view lifecycle owner or the view lifecycle. This is a very particular lifecycle that is only available after on create view and until on destroy view. With this one you are actually totally safe because at this time when you actually come back to the, when the view is going to be destroyed, this is going to be marked as destroyed and the observer is going to be removed automatically. You have again your beautiful setup. You don't have to do anything that is additional remove codes. The architecture components are coming back to the promise to be very simple and help you with the application development. But now you actually have two life cycles. This is actually really confusing because suddenly you have to decide which one do I use. Do I use the fragment lifecycle? Do I use the view fragment view lifecycle? Which one of those is actually the right one to use at which kind of moment? Now we're going to step back a little bit and look at the architecture and try to figure out what would be a good practice actually to use, which of these kind of life cycles at what time? So in general we observed certain kind of pattern around applications and how they are abstracted basically in different kind of steps. And so one of the level of obstructions is that we are using the navigation basically which is the top, most top level abstraction of any kind of application. In this kind of abstraction we're going to do things like starting activity, starting fragments, dealing with the backstack, et cetera. So this is the, you can say, the higher level. Then in the second level of abstractions we have use cases. They're going to deal with your individual business logic on a screen basically. Things that you're doing there is composing views, showing arrows, dialogues, dealing maybe with permissions. It's basically your core business logic implemented. And then there is a third level which is basically a cross-cutting level for if you want to reuse certain kind of aspects of your application. That is basically like showing data, manipulating data. You can think of this like, for instance, like a list view with a complicated filter mechanism that you want to reuse across all of your application. So these are the three basic abstractions. And I'm going to now discuss how we can actually deal with these kind of three abstractions with the lifecycle. So there's the simple approach. In a simple approach, the activity is basically going to observe a view model. And the view model is taking care of both navigation and use case. So you can think of this as a very simple activity that deals with composing different kind of fragments on the screen to show everything related to the use case. And if you move to another use case, it's going to take care of composing these use cases again together. And so this is basically the... It would still work as the other life data example. Whenever anything changes in the view model, it would basically move to the other state. So what is it doing? It actually shows fragments. And the fragments are here actually observing with the view lifecycle. Not with the fragments lifecycle, but the view ones. And to just basically avoid all kind of pitfalls here. And we are observing then any kind of object that is dealing only with the view. So you have a very, let's say, simple construct. So if you're just building a simple application, I think this construct is good enough to basically hold most of the cases. So how does it look like in code? So you have the view model. So here I used an example where I have something like a name list view model, a list of names. And you have a state here. That's the view state. It's only the fragment example because I avoided the activity for the example's purpose. And then in the fragment, we have, we're going to, in onCreate, onViewCreated, we're going to use the view lifecycle owner to basically observe only the changes of this particular list. And we are good to go. And that's going to be like for a simple application, I guess, the 90% case for you to basically manage both moving around from one fragment to the other, composing everything and having kind of a safe ground here. But if you're moving a little bit further, and as we do in our application, actually, we're growing bigger, you kind of have to do a one-level higher up structure. And here you actually start to think of the navigation as something that is completely independent of the use cases. You're basically just saying, okay, I'm navigating from A to B. I don't really care what is in B. I'm just going to basically tell the fragment to just be displayed, and I'm not actually dealing with what is inside the fragment, more or less. So this is a very nice way to actually build applications because at this point, you don't actually have to deal with any kind of business logic that is low-level. And so what is the fragment then doing? Internally, it will basically still deal with the two life cycles. It's going to use a higher level of life cycle to deal with the use case-specific things, and I'm going to come back to an example of what this could be. And then with the all view-related stuff, it's going to still observe in the view model with the view life cycle. So you would have basically two separated parts of a within your fragment. How does this look in code? So first of all, as I promised, the use case could look like this. So you enter the fragment and you have different kind of aspects of this particular business logic. You want to show a list. You want to maybe edit a name by long pressing on it or stuff like that. You have to deal with some kind of network error because you fetched a list from the network, or you are just in the loading state at this particular moment. So these are certain kind of things. They are not really view-related in particular. We're just describing a high level situation of this particular use case. And then you still have the, so you would represent this in a live data object that is the use case state. And then last but not least, you would have still the known view state that is basically representing the live data object of the state. And you would update all kinds of constructs here. You might need actually for each individual part of the view, you might need an own live data object here. So this sounds a little bit cluttery because you're actually putting a lot of code into your view model at this point. This kind of screams on putting this in a one level deeper actually. So I forgot actually to show the fragment. How does this implement it? So in the fragment, you actually in onCreate, you will still use the fragment's lifecycle to observe the use cases parts. And then you would show and hide basically views more or less, or compose them, reinflate them, whatever is necessary actually for you to actually dealing with this particular problem. And then in onViewCreated, you would use the view lifecycle owner to still observe basically the view state of your view model. And then you're still basically safe to only deal with and update your view. Okay. So in our application, we are building, we are coming actually to the situation where we are finding ourselves more and more that this kind of approach that I just presented, which we are actually using in a similar way, is actually not scalable enough because we might have to deduce, we might have to, we have way more view aspects that have to be maybe moved to a different part, and they have to be reduced because we are keeping the same patterns across the application again and again. And so of course, it would be a pity to basically just rewrite this kind of views over and over again. So basically, we are moving more and more towards actually composition than using the extension case, where you would just basically take the view model and extend it to have a different kind of functionality. The good parts about extension, about composition is that you have really clean responsibilities and very clean documentation of what your component can do actually. So, and testability is actually really great. So how does this look like? In the composition case, again, high level activity is taking care only of the navigation, still the same. It's going to show fragment and the fragment is only taking care of one thing. And that's with its own life cycle, it only takes care and observes the use case information. And once you actually get any kind of information about how to change the use case, you're actually going to deliver it on the third level actually, on the view container or like a view level, you could say, where we're going to use the view life cycle. So this is going to be then hold internally and there it's actually observing its own view model and it's going to update basically aspects of itself accordingly by using the same. So how does this look in code as an example? So in, again, we have the same kind of view model, but now it's split up, so I don't show this again here anymore. So the one part of the view model is actually in onCreate. We can switch around, depending on the use case, we can switch around and change basically the view. Like for instance, we would change the visibility of the name list view. So this is just not a simple kind of view, it's a little bit of extended custom view, you could say. In onViewCreated, we will actually not use the life cycle, but pass down to the view. And if you follow the Google I.O. 2018, you actually have seen that, especially with data binding, this is going exactly into this kind of direction where we're actually passing directly with the view life cycle owner, passing directly the life cycle to the data binding component that is dealing with binding directly to the view. But here now you have a more general pattern that you can actually use by building views that you can reuse across your application. And so we pass this down, and this is how a possible custom view could look like with Kotlin. It's actually quite nice because it's just the constructor is very, very thin. And in the attach method, we are doing exactly what we used to do actually in the fragment. We're just basically going to get the view model, and then we're going to observe it, but with the given life cycle. And of course, this is helping a lot with testability because this is not related to any kind of activity or fragment code, and it's really plain and simple. A good other aspect of this is that you can now compose your views actually with higher level logic in XML, and you can give it attributes to actually instantiate a different kind of behavior that you can then pass to your view model and have basically a different kind of higher level view. And this is, that's all. Thank you.
 Hello. Hello, everyone. My name is Simon Yerkes and I'm working at here Technologies.  And today I'm going to talk a little bit about how to survive the life cycle.  And this is mainly around the architecture components and how we actually deal with the certain kind of life cycles that they are now introduced to us.  And for this I'm going to do a little bit of a short introduction to this kind of, let's say objects, you could say.  So in general, everybody is more or less aware of the architecture components. Raise your hand if you have heard of it.  I think everybody knows nowadays about this. I just give a very short recap, like two, three minutes, just to be really on the same page.  Because some of the things that I'm going to talk about later are going to have to have some recap, basically.  So first of all, the life cycle. The life cycle is basically just an object that was introduced to hold the state of activity or fragment.  And basically represent, not hold, but represent the state of activity or fragment and give you the opportunity to be notified about it.  So this sounds simple, but it is actually something that changed a lot in the architecture or in writing good applications.  Because now you can actually make some guarantees and you can also subtract certain kind of aspects from your application that should never touch an activity or a fragment.  Also a very interesting part of this is that the life cycle is actually provided by a certain kind of guarantee.  So the steps here, like on create, on start, they are always basically called in the same kind of order.  And building on top of this is way better now because previously in the different versions you had some issues with this kind of ordering.  As a second object that we just recap quickly, we have the life cycle owner.  I'm going to talk a little bit about more life cycle owners later.  And it's basically just an object that holds a life cycle.  And so you could build your own life cycle owner if you need to, if you want to build your own UI framework.  And last but not least, in this kind of three important objects is the life cycle observer.  And the life cycle observer is helping us to actually realize when something happened, when something changed within the life cycle.  And here I took the Android X life cycle, a library, and there you have some new kind of servers.  Like for instance, the full life cycle observer, which is a really nice different implementation than using the annotations, which is a little bit less efficient.  I hope you already started to use Android X.  Nobody? Well, it's pretty fresh, right?  So on top of this, Google in the IO 2017 introduced a very useful object that is called the life data object.  And this is just basically an emitter observer pattern where you can hold an object and it's going to react on your life cycle.  And this sounds very simple, but it's actually changed a lot, at least in our architecture, on how we build applications.  Because now you don't care about the life cycle anymore, you're basically just emitting data, you're producing it,  and whenever anything happening through the life cycle, you just get informed correctly.  Very important here to mention it, that it starts to emit data when it's fresh, when you come actually in the life cycle on start,  and it's going to automatically remove all the observers in on destroy.  And we're going to come to this point in a second because it's actually important to realize this.  Last but not least is a concept that's the view model that is basically holding everything together  across activities of fragments when they are destroyed.  And this is the view model.  The view model is nothing more than basically kind of a retained state where you can add a life data object  or any kind of other objects that are going to be hold across basically the life cycle of your, of an activity or fragment.  So with this three, five simple classes, you can actually do really, really cool stuff.  But how do you actually bring everything together?  So first of all, from Android X on, we have those kind of life cycles built in,  and also with the appcompens 26, I think.  You get all of these life cycle objects basically built into the standard libraries,  and there are three of them that you should realize.  And I'm going to talk about the last one in a second, and the first two are basically the fragment life cycle owner,  sorry, the fragment activity life cycle owner, and then the other one is the fragment life cycle owner,  and the new one that is introduced now with the, and the Google I owe 2018 is the view life cycle owner.  And that's a particular one because it's a little bit different.  It's not totally intuitive what it is doing and why is it there?  Who have you heard actually of the view life cycle owner?  Okay, just a few hands raised.  So this is good because I think this talks mainly about putting awareness on this new object.  Okay, so how does it work?  So this is just a general recap, and maybe you're realizing the style a little bit  because I copied it from the Google I owe slides more or less.  So on the top, you can actually see the view model that holds some kind of data in life data object,  and it's going to emit something, and this something is going to eventually be drawn on the fragment.  But the fragment first needs to go through some kind of cycle, and the cycle starts with on create.  So this is just a normal call, a normal life cycle method.  At this point, we're going to actually register because the nice thing about those kind of life cycle methods  you can just do everything in one method and in the on create method in this case.  We start to observe, but at this point we are not getting actually this kind of value delivered right away,  but we kind of have to wait until we are notified to be on start.  On start at this point it's actually safe to draw anything on the screen and changing basically the view.  And then we actually get delivered this kind of object and we can do something about it.  Interesting is then if we are moving towards like if we're rotating for instance a fragment,  then we are actually going to of course we get the on stop event and we are marking our observer as inactive.  At this point we will not deliver any kind of further update anymore.  So this means any object B that you can see here on the right is not actually going to be delivered  and it's also going to be marked internally as not delivered to this particular observer, which is an important aspect.  So then the fragment is going to be destroyed, all the resources going to be removed,  and then eventually also the observer is going to out remove itself.  So no more boilerplate code to just go on destroy and unregister your observer.  It's a very, very clean setup basically.  And in our applications actually it helped us a lot to have a very, very simple way to describe what is happening in your application.  So what is happening next? We have the rotation case.  So once you rotate the fragment, a new fragment is going to be created.  We go through the same stages.  On create it's going to be called we start observing again.  And then we're going to go through on start and on start.  We got actually the value that was not delivered previously is now delivered freshly to us.  And so from there on we can actually draw the updated value.  So you can realize that it's basically a very simple concept, but it actually helps a lot to build anything that is going asynchronous  and anything that shouldn't be bound to the view.  Who of you is actually aware of this kind of life cycle and understood it already previously?  Okay, that's nice. Perfectly.  Then I hope you're going to have a little bit more input on the or fun on the next part.  So this helped us actually to do simple setups like this.  So you have basically in on create on the fragment, you could actually just get the view model.  And then from the view model, you would basically just observe the, you would just observe the with the fragments life cycle.  You would observe the changes on the view model and then you get actually delivered this object B.  Who of you knows actually that there's something wrong about this or problematic?  Just a few hands.  So who of you is using this kind of construct?  Okay.  Not too many actually.  So I'm surprised.  Okay.  So what is problematic about this?  So if we are not talking about the case of rotation where fragment is going to be destroyed, but we're talking of the case when we actually moving from one fragment to another in a fragment manager.  So like a backstack case, you're moving like from one fragment to another and then you go back to your previous one.  So few of you might know that at this point we are actually keeping the fragment in the memory, but something else is happening.  So first of all, let's go for the same cases.  So we have the life data object that is going to emit the object A. We go through on start and we're going to draw this again on the fragment.  Then we are actually moving to the other fragment.  At this particular point we are keeping the current fragment actually in the fragment manager.  We just call on stop.  Then we're going to detach the fragment from the view and we're going to start the other fragment.  The other fragment is started at this particular point and it's going to do its magic, whatever we need to do that, and then we eventually press back.  When we press back, the previous fragment is going to be reattached.  Then it's going to its own cycle again, it's going to call on start, on start is going to happen, and then we mark our fragment as active again.  Who of you sees an issue with this?  Because we have had the same observer as previously, we actually marked A as already delivered.  But what happened in detach and attach again is that we actually destroyed the view.  There's a brand new view at this particular moment when we reattach the fragment.  This view doesn't know anything about A.  What you're going to show at this particular moment is an outdated view.  This is a problematic issue.  You can solve this issue with two kinds of ways.  One way would be to actually tell the view to render this object A again.  You can just call this clattery setup, which is making your app very ugly.  Basically calling an onCreate, they change the view method that is basically going to be used again on view created,  where we basically check if we have actually a value and then we call it again to basically redraw it.  At this point you're basically saying if you are on the same page like the object A.  Another setup many developers are using is actually this.  This is also what our application has used a couple of weeks ago until I actually fixed and removed the bug that is coming from this.  We actually would, on view created, we would listen to the observer.  We are fine because it's a new view and then we get also a new observer.  At this particular point we would always be notified when any object was changed with this observer.  The problem with this is that we are still using the fragment lifecycle.  The fragment lifecycle is not destroyed because we are keeping it in a memory.  When we are coming back we would call this method a second time.  Of course, can you imagine what happens at this particular time?  We will create a second observer and suddenly we have two observers.  We also keep actually, we can keep a reference to the previous view and by that leaking memory.  A way to solve this problem is to call and on destroy view, remove the previous observer.  This was a fix but you can see it clatters your code a lot.  Especially if you have a lot of life data objects that you want to listen to,  you're going to have a lot of this kind of boilerplate code.  Of course, this is jeopardizing the whole idea actually on how to use life data and the lifecycle correctly.  In the Google I O 2018 they realized we have to dedicate a certain kind of lifecycle for this.  This is the view lifecycle owner or the view lifecycle.  This is a very particular lifecycle that is only available after on create view and until on destroy view.  With this one you are actually totally safe because at this time when you actually come back to the,  when the view is going to be destroyed, this is going to be marked as destroyed  and the observer is going to be removed automatically.  You have again your beautiful setup.  You don't have to do anything that is additional remove codes.  The architecture components are coming back to the promise to be very simple  and help you with the application development.  But now you actually have two life cycles.  This is actually really confusing because suddenly you have to decide which one do I use.  Do I use the fragment lifecycle?  Do I use the view fragment view lifecycle?  Which one of those is actually the right one to use at which kind of moment?  Now we're going to step back a little bit and look at the architecture  and try to figure out what would be a good practice actually to use,  which of these kind of life cycles at what time?  So in general we observed certain kind of pattern around applications  and how they are abstracted basically in different kind of steps.  And so one of the level of obstructions is that we are using the navigation basically  which is the top, most top level abstraction of any kind of application.  In this kind of abstraction we're going to do things like starting activity,  starting fragments, dealing with the backstack, et cetera.  So this is the, you can say, the higher level.  Then in the second level of abstractions we have use cases.  They're going to deal with your individual business logic on a screen basically.  Things that you're doing there is composing views, showing arrows, dialogues,  dealing maybe with permissions.  It's basically your core business logic implemented.  And then there is a third level which is basically a cross-cutting level  for if you want to reuse certain kind of aspects of your application.  That is basically like showing data, manipulating data.  You can think of this like, for instance, like a list view with a complicated filter mechanism  that you want to reuse across all of your application.  So these are the three basic abstractions.  And I'm going to now discuss how we can actually deal with these kind of three abstractions  with the lifecycle.  So there's the simple approach.  In a simple approach, the activity is basically going to observe a view model.  And the view model is taking care of both navigation and use case.  So you can think of this as a very simple activity that deals with composing  different kind of fragments on the screen to show everything related to the use case.  And if you move to another use case, it's going to take care of composing these use cases again together.  And so this is basically the...  It would still work as the other life data example.  Whenever anything changes in the view model, it would basically move to the other state.  So what is it doing?  It actually shows fragments.  And the fragments are here actually observing with the view lifecycle.  Not with the fragments lifecycle, but the view ones.  And to just basically avoid all kind of pitfalls here.  And we are observing then any kind of object that is dealing only with the view.  So you have a very, let's say, simple construct.  So if you're just building a simple application, I think this construct is good enough to basically hold most of the cases.  So how does it look like in code?  So you have the view model.  So here I used an example where I have something like a name list view model, a list of names.  And you have a state here.  That's the view state.  It's only the fragment example because I avoided the activity for the example's purpose.  And then in the fragment, we have, we're going to, in onCreate, onViewCreated, we're going to use the view lifecycle owner to basically observe only the changes of this particular list.  And we are good to go.  And that's going to be like for a simple application, I guess, the 90% case for you to basically manage both moving around from one fragment to the other, composing everything and having kind of a safe ground here.  But if you're moving a little bit further, and as we do in our application, actually, we're growing bigger, you kind of have to do a one-level higher up structure.  And here you actually start to think of the navigation as something that is completely independent of the use cases.  You're basically just saying, okay, I'm navigating from A to B. I don't really care what is in B.  I'm just going to basically tell the fragment to just be displayed, and I'm not actually dealing with what is inside the fragment, more or less.  So this is a very nice way to actually build applications because at this point, you don't actually have to deal with any kind of business logic that is low-level.  And so what is the fragment then doing?  Internally, it will basically still deal with the two life cycles.  It's going to use a higher level of life cycle to deal with the use case-specific things, and I'm going to come back to an example of what this could be.  And then with the all view-related stuff, it's going to still observe in the view model with the view life cycle.  So you would have basically two separated parts of a within your fragment.  How does this look in code?  So first of all, as I promised, the use case could look like this.  So you enter the fragment and you have different kind of aspects of this particular business logic.  You want to show a list. You want to maybe edit a name by long pressing on it or stuff like that.  You have to deal with some kind of network error because you fetched a list from the network, or you are just in the loading state at this particular moment.  So these are certain kind of things. They are not really view-related in particular.  We're just describing a high level situation of this particular use case.  And then you still have the, so you would represent this in a live data object that is the use case state.  And then last but not least, you would have still the known view state that is basically representing the live data object of the state.  And you would update all kinds of constructs here.  You might need actually for each individual part of the view, you might need an own live data object here.  So this sounds a little bit cluttery because you're actually putting a lot of code into your view model at this point.  This kind of screams on putting this in a one level deeper actually.  So I forgot actually to show the fragment. How does this implement it?  So in the fragment, you actually in onCreate, you will still use the fragment's lifecycle to observe the use cases parts.  And then you would show and hide basically views more or less, or compose them,  reinflate them, whatever is necessary actually for you to actually dealing with this particular problem.  And then in onViewCreated, you would use the view lifecycle owner to still observe basically the view state of your view model.  And then you're still basically safe to only deal with and update your view.  Okay.  So in our application, we are building, we are coming actually to the situation where we are finding ourselves more and more  that this kind of approach that I just presented, which we are actually using in a similar way,  is actually not scalable enough because we might have to deduce, we might have to,  we have way more view aspects that have to be maybe moved to a different part,  and they have to be reduced because we are keeping the same patterns across the application again and again.  And so of course, it would be a pity to basically just rewrite this kind of views over and over again.  So basically, we are moving more and more towards actually composition than using the extension case,  where you would just basically take the view model and extend it to have a different kind of functionality.  The good parts about extension, about composition is that you have really clean responsibilities  and very clean documentation of what your component can do actually.  So, and testability is actually really great.  So how does this look like?  In the composition case, again, high level activity is taking care only of the navigation, still the same.  It's going to show fragment and the fragment is only taking care of one thing.  And that's with its own life cycle, it only takes care and observes the use case information.  And once you actually get any kind of information about how to change the use case,  you're actually going to deliver it on the third level actually, on the view container or like a view level, you could say,  where we're going to use the view life cycle.  So this is going to be then hold internally and there it's actually observing its own view model  and it's going to update basically aspects of itself accordingly by using the same.  So how does this look in code as an example?  So in, again, we have the same kind of view model, but now it's split up, so I don't show this again here anymore.  So the one part of the view model is actually in onCreate.  We can switch around, depending on the use case, we can switch around and change basically the view.  Like for instance, we would change the visibility of the name list view.  So this is just not a simple kind of view, it's a little bit of extended custom view, you could say.  In onViewCreated, we will actually not use the life cycle, but pass down to the view.  And if you follow the Google I.O. 2018, you actually have seen that, especially with data binding,  this is going exactly into this kind of direction where we're actually passing directly with the view life cycle owner,  passing directly the life cycle to the data binding component that is dealing with binding directly to the view.  But here now you have a more general pattern that you can actually use by building views that you can reuse across your application.  And so we pass this down, and this is how a possible custom view could look like with Kotlin.  It's actually quite nice because it's just the constructor is very, very thin.  And in the attach method, we are doing exactly what we used to do actually in the fragment.  We're just basically going to get the view model, and then we're going to observe it, but with the given life cycle.  And of course, this is helping a lot with testability because this is not related to any kind of activity or fragment code,  and it's really plain and simple.  A good other aspect of this is that you can now compose your views actually with higher level logic in XML,  and you can give it attributes to actually instantiate a different kind of behavior that you can then pass to your view model  and have basically a different kind of higher level view.  And this is, that's all.  Thank you.
_DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_0_1319.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_1320_3323.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_3324_4415.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_4416_8399.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_8400_9167.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_9168_9911.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_9912_12635.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_12636_12947.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_12948_13739.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_13740_14507.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_14508_14843.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_14844_15071.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_15072_15683.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_15684_16619.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_16620_17507.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_17508_20891.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_20892_21575.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_21576_22367.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_22368_23783.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_23784_23879.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_23880_23927.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_23928_25283.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_25284_25679.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_25680_27071.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_27072_27167.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_27168_28727.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_28728_31823.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_31824_33311.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_33312_33635.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_33636_34151.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_34152_34367.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_34368_35975.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_35976_36239.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_36240_36803.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_36804_37319.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_37320_37571.png _DCBerlin18_408_Joecks_How_to_Survive_the_Lifecicl_BqzGRiNS-do_37572_37583.png