Exploring Jetpack Compose: MVVM Architecture

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
gasp switch okay nope it's not gonna work we're gonna have to switch the scene myself how's it going happy wednesday glad to see all of you again i was off last week celebrated my birthday which was nice i'm excited for tonight's stream uh i'll fill in some fluff for a few minutes but one of the reasons i'm really excited about this one is we're finally trying out this little thing which is jetbrains projector so if you all are unfamiliar with what jetbrains projector is is it's basically a solution i mean the short answer is it's a solution to running jetbrains ides in the cloud and then rendering those ids either in a browser or in the native client that jetbrains makes so i am using the native client um this might not look like it to you all but this is effectively kind of like a browser running android studio it's actually running on a virtual machine that i set up in google cloud um but it's the real ide the way it works from a technical standpoint i guess is because intel j is made using java swing there's some way to render java swing apps in the browser and so you can run the intellij id in the cloud render it in the browser and then use it wherever you go so two weeks ago we had um like the stream just broke in the middle basically uh we started dropping a bunch of frames everything just went terribly and i assumed it was because even though i have a pretty good laptop it was just overloaded with running the ide and chrome and streaming etc but so i looked into this as a solution to maybe if i can offload all the ide work then hopefully we don't have that happen on streams anymore and actually according to streamlabs which this is actually ridiculous if it's true but it's telling me i have zero percent dropped frames and i've never actually seen that while streaming before so that's really fascinating hopefully we have crisp audio crisp video throughout the whole stream and we should still have the same performance from the ide i even have usb debugging set up the way that works if you're curious is basically having to like ssh onto the machine using a certain port number that connects adb so now i can run an apk from a completely different computer onto my own device um that's not really the point of tonight's stream i will probably be working on blog posts and a video to show you all how i set that up um but it was really cool and i just wanted to brag about it and also we might have better performance because i updated mac os as some of you might recognize the big sur background um yeah that's me no one wants to post any updates on chat but i hope you all had a good two weeks hope everyone's doing well um let's talk about what we are going to do tonight um yes let's see how it performs hopefully well one of just a kind of a disclaimer about that is like i've just been excited to have set this up and been able to run an app on my phone but i haven't sat here and like tried to build a feature using projector so i'm a little curious to see if there's any nuances in my workflow that i'm going to find while we're doing the stream occasionally i have a couple weird issues with some keyboard shortcuts specifically like the copy and paste sometimes but it will be fun to work those out also of course projector is in sort of a early stage still um but jetbrains is open to feedback so if i do come across any bugs i'll try to go report them later um i've tried so i think this is a problem even when running my own ide i don't know if i can change the font size of this window but i did bump up the font size within the text files themselves so hopefully you'll find this readable when we start coding but as always let me know if there's anything i can do to make this easier for you all to follow um so this app if you all are unfamiliar with the one that i have on screen um i think three weeks ago we did a jetpack compose code along where we wanted to run a build one of the android dev challenge apps so we built this one called bloom and it's not really a fully functional app it's just a bunch of static screens actually we have this welcome button like create account doesn't actually do anything but if you log in that takes you to a login screen and you can type some stuff in here um you can type in a password but we don't even do any input validation you click login and then we go to this home screen and it just shows you a list of plants and stuff and that's that's that right so that's all built i mean we even have the search but oh we didn't even deal with like typing into the search field um so we're not gonna what we're gonna do today i had an interesting request on twitter um which was to kind of explore like all of the all the android development buzzwords with compose right how do i use mvvm how do i use room how do i use retrofit um and i think that's actually like it's a good question um i think those questions are important for any app and one of the things i like about it is like if you are a developer working on an existing application and you're already using all of those tools there's a good chance you won't actually need to change much in order to work with compose if you're already using the android x view model you'll be able to use that within your compose applications and you can do that whether you're using live data whether using state flow etc but it's still good to see that in action so what i thought we would do today is to take this bloom app that we built and try to make it a little bit more like a real app and maybe set up like an mvvm architecture that displays this information um but we could even have it served either from like in-memory stuff or maybe we can pull this from a room database i don't think i'm gonna do that today i think for today it would be good to just discuss like the mvvm architecture and then how we can use that within like our compose functions i hope that makes sense i hope that sounds interesting um if anyone in chat has any preference on like what screen we use this for i'm open to that because i thought about a couple different ideas you know we don't really need to set up thinking at a high level we don't really need to set up an architecture flow for like this welcome screen um i mean we could set up something but it's really just two buttons and we don't actually lead into like a create account screen we could maybe show like how to do the login flow and discuss like input and password validation i think that'd be interesting i don't know if that's what you all want to do tonight or what maybe be more interesting is dealing with mvvm on the home screen so how do i create a data source that pulls all this plant information um and shows that on the screen maybe we can show how we deal with like loading and empty states as well inside like a compose application i think that's what people would be interested in you know let me know in chat real quick if any of you have a preference um i'm kind of at the stage in like streaming some of these projects where i personally have like run out of ideas and so i kind of lean on those of you who come in here all the time and like what do you want to learn about and we can figure out how to build build that together if any of you are interested in the project by the way i believe you can do exclamation point github and that should link to this project um so you can find the code that's already there if no one in chat is feeling eager i think main screen how renders adding new stuff on the fly okay that'd be interesting um all right let's do that let's let's dive into the main screen so in thinking about this today i was also wondering you know how um what's the word i guess where i want to start in this conversation because maybe before looking at code it'd be good to have like a refresher on how like what the mvvm architecture even is right because also this stream i plan to put up on youtube so for people watching there you know maybe you're not maybe you're coming into this wanting to understand what nvm architecture is in the first place so maybe it'd be good to kind of talk about that at like a high level first and really we can do that in like 30 seconds um just to show y'all uh what it works so i'm going to this website draw.io which allows us to create some diagrams and i want to do that to describe all the moving parts and i promise this won't get if you're like anxious please don't give up on the stream this will be just like three bubbles but i want to talk through how an architecture pattern works so we have everything we need for the rest of the stream right so let's let's create these bubbles right we we talk in these acronyms one of the things i don't like about the architecture discussion that happens all the time is like acronyms feel very buzzwordy right like what is nvvm mvp oh god you can't read that can i change that didn't work why aren't you updating ah that's not what i want no i don't sorry i'm trying to figure out if i can update this font size or not apparently i can only do it after one of the things about the architecture discussion right is like we have all these confusing acronyms what is mvp what is mvvm what is mvi etc uh so let's take them this mvvm1 and let's talk about what those components are so we have a model right that's the m the v stands for view and the vm stands for viewmodel and let's talk about how these what these three components mean so you can think of an architecture as a way of splitting up responsibilities in your application right one way i like to start the architecture conversation is the implicit fact that we all know but sometimes forget you can't write all of your code in one file right obviously for readability concerns but then that's just not scalable it's hard to maintain it's hard to update it's hard to swap things in and out right so it's good to split up our code into different files into different responsibilities and then that becomes an open question well how do we do that and i have a really great talk i've given before i can even pull up the blog post i'll share in chat if you are interested in i still have caps on if you are interested in learning more about the different architecture patterns i would definitely recommend reading through this post but the short answer is i i personally recommend nvvm so we're going to talk about how that one works so let's go over each of these components real quick you have your model right and that is your data source so this could be um a database a network um file system event and this class or series of classes should only be responsible for displaying information yes exactly nvwtf you have your view component which is it displays information and it's important to note does not care where it came from so like your view should just know i have this information and i know how to display it to the user i don't care where this data comes from the view doesn't care if you use database to view doesn't care if you use a network right um it also should um it should not do any you know it can handle like input events but it doesn't do any business logic so does that do like um validation data manipulation etc right so that's just an important thing to keep in mind oops can i make this bigger so it fits and then all that other stuff that i didn't mention you know that kind of gets lumped into the view model and that's kind of dangerous because depending on your app this could end up being like a god class right do you think this knows how to fetch data deals with data and manipulation right it will deal with like button actions but then let's say i have like a submit button on a form what i'm saying is your view should handle that button click but the view should not do any validation on that data that would actually happen over here in the view model portion and maybe you know if we do architecture on the login screen in bloom that would make more sense um sorry if i misspoke there um yeah actually let's update that that's a good point so displays information handles click touch etc events um and then your view model kind of does everything else knows how to fetch data deals with data manipulation deals with input validation um i don't know what else we could put inside the view model um i don't know if i'm thinking like side effects like analytics or something let's leave that out for now i think that's a conversation that goes beyond what we're trying to do today so these are the three components that make up mvvn state management thank you i that's like the number one thing this is for um and i forgot it um yeah state management is good and when we do code we're going to talk about that a lot because i'm going to show you a really good approach to using like data classes for managing state and that will be really helpful especially with a ui framework like compose so i hope this makes sense and of course you know let me actually please hold while my adhd brain uh jumps into another thing that i usually do on streams and i haven't done in a while but i'm gonna do this real quick um i will talk through it so you know what i'm doing so when i started streaming i recognized that not everyone would always feel comfortable asking questions um sorry what is today's date april 7th uh asking questions in twitch chat so one thing i did was make a um a slider link for like anonymous questions that people could um post their questions throughout the stream if they had any uh feel free to go ahead and use that link um obviously if you are comfortable posting your questions in the twitch chat i'd appreciate it because i have that always open but when i hit certain break points in what i'm doing i will go ahead and check out that slidoo link so that if you have questions you don't want to ask in stream but you can post them there and then that way i can still get to your questions i hope that's helpful i posted the link there and then it should run periodically but there's also a nightback command to get those links if anyone needs it back sorry about that tangent because i thought that was a good breaking point in this quick first discussion is these are the three components that we work with so the next question we need to ask is well how do these interact with each other and we can kind of do that with like arrows right so the first connection that i guess i want to talk about is that the view model is responsible for fetching data right so the view bottle talks to the model request information and then the model passes that information back and i guess um do we wanna i guess we could just double end the arrow um and i guess it's hard to know if you really want to call that two ways right but i think it's two ways like i i call to you and you give me information back but on one hand maybe it doesn't come the model never has a reference to the view model so actually maybe maybe i'm confusing myself let's not do a two-way arrow we'll just say the viewmodel goes to the data or goes to the model and gets information and then we do have this sort of um we do kind of have like a two-way connection between the view and the view model and this is where the conversation gets interesting um because this line here uh i think some people like to mark it as a dash it's kind of like a artificial connection so when i think of like a direct connection we're saying the view has a reference to the view metal and it can call like viewmodel.loaddata it can actually call a function the model doesn't do that the other way around instead what the view model is supposed to do is it exposes state um yeah oh let's bump this up whoop so it exposes state via something like live data or flow and view subscribes to it so the view model itself is never actually manipulating the view what will happen is the view will listen for updates and it will know how to respond accordingly and we're going to see that in code if that doesn't make sense in wording but it's good to understand like that's actually a key point of the mvvm architecture is that you don't have a reference back to the view the view model just throws out the state says here's what my state is and the view listens to it and responds accordingly um and then when the view talks to the view model what we do here is um this is where we're gonna do things like you know um notify button clicks forum input lifecycle events if necessary etc um so that's kind of the connection there and this is really short but this is all it is um i think again the architecture conversation can become very complicated um and when you deal with like scaling of apps and really thinking long term i understand that but i don't think it needs to be that complicated i think you can just look at it as these kind of like three responsibilities understanding what each of these responsibilities are and how each of them communicate with each other and i really wanted to put out this sort of quick flow chart because when i start writing this in code having this mental model will help a lot um you know for those of you who are here in the beginning and got to see this so hope that was helpful i'm actually checking no questions on this yet let me know if you have questions about the nvvm architecture before i move on oh also uh virgo thank you for the follow an alert should have gone off but it oh maybe you followed before i started coding and so the alert box didn't go off but it should be on looks like it's on um we need to pause oh and oh man all right i apologize chat um you know i'm not even gonna switch to my be right back screen i will be back in 30 seconds um oh yeah hold on i will answer sue house's question in a second um some of the original streams are on youtube but after a while i fell behind in updating them but i'm gonna try to be better about that moving forward i didn't do the one from two weeks ago because everything broke in the middle um but yeah hold on i will be right back in one second i need to grab something from prince all right um so my adhd brain has jumped over a lot so far this stream i'm very sorry but one thing i'm really excited about is one of my favorite seasonal beers brewed where i grew up in michigan is um finally here in new york it came out like two or three weeks ago and like it takes a while for it to get to new york city but it is so i'm very excited cheers everyone all right now that we have that um yeah it was from august a weekend stream i think it might be on youtube um but let's check real quick um yeah so there's some study guide stuff um oh yeah here's another one implementing model hello so feel free to watch this but um we're basically going to do all the same stuff today uh but we're just going to be building it into a composed application and not much is going to change from the architecture side um except for basically how that viewmodel gets created and used um but it looks like those of us who are here are good on these components so let's dive into the code and start talking about that okay so looking at this home screen i'm just thinking about all right let me take a step back let me tell you where i like to start when i'm thinking about architecting a screen so to reference these um one thing that i find as an easy place to start is creating your sort of model layer because it doesn't have dependencies on anything else right it just needs to fetch data so we can actually build that out so let's go into our project and let's create a new file and an important part of building a data layer with any architecture is understanding something called the repository interface a repository pattern and what that means is anytime you have something that is requesting data and let's put this on a new branch anytime you're requesting data you want that data service to be behind an interface and this is really important so that you can create an implementation based on whatever sort of sorry please hold everything is wonky on my screen so that you can swap out these implementations so i can make a data source that uses an in-memory service i can make one that uses networking one that uses a database and be able to easily swap them out if i have a new model that directly depends on a room database and i suddenly don't want to use room anymore this becomes very hard to fix so it's important to put your data layer and really this is true of any dependencies behind an interface so let's create our plant repository and let's talk about what that looks like for this home screen so for now we just want to deal with the same screen that we already have but it would be fun to look at some options later where maybe we treat these as two different data sources we'll have a network request to browse the themes and one to browse the home garden right home garden items so let's write those out let's create one suspension function called fetch themes and this will return a list of plant theme that is a class that we defined uh when we built the app and it just has like the image res and the title and we actually hacked it and used the same uh data class for the home garden items so for now i'm not going to change that i'm going to keep the setup we already have and but we'll still treat them as two function calls so then we can have fetch home garden items which request plant theme um there's a question here about how thorough we want to be in this walkthrough and i think for this one i'm gonna keep it kind of high level the reason i just thought about that is um this method signature right here when we think about it specifically the return type so i'm saying that every time i call fetch themes i'm going to return a list of plant themes and in the real world that's not always accurate right like i could be requesting i could get an error and i think for this example we're going to say that that can happen um but i think it would be nice to either do like a stream or video or something where we walk through like how we can handle errors in data requests on android um i think that people would be interested in that uh if you're interested in seeing that we can kind of talk about it towards the end of the stream but for now let's kind of assume like a happy path flow here and let's add some documentation as people find this and to reiterate what we talked about so um plant repository serves as the model layer for our home screen this allows the user to request themes and garden items oops i actually wanted to rename this to fetch home garden items and to clarify ah my photo covers this how do i there we go um we use an interface so that we can create multiple implementations and swap them out hey no problem henry thank you so much for the suggestion on this um hope this has been interesting so far so we've created our interface now for the app that we're building today for replacing our home screen um i think it would be cool to look at retrofitted room but i'm going to keep those things sort of out of scope and just focus on the mvvm aspect of it so the next thing we need to do now that we have an interface for our model layer is to create that concrete implementation so let's do that and let's call it in-memory uh plant service that's kind of the naming convention i like to use where my implementation of a repository is a service that's just personal preference this is a plant repository and we'll implement those members so when we were building the compose app for the stream a few weeks ago um we made these hard-coded lists of all the data that shows up that has the image drawable and the title and for now we're just going to have like our in-memory service return those same things so let's for here we'll do return default plant themes and then here we'll return home garden themes i guess i called it themes last time let's rename this to items i like items here so this is our plan service so that's the data layer like i said it's short and sweet have an interface for your data requests and have the concrete implementation wouldn't have been so short if we were trying to implement retrofit uh maybe that's something we could do next time um so now let's go back to our overview so we've created this component now the next thing we could build is here we could build our view model that's responsible for state management and knowing how to fetch data can you use firebase for this you could so the nice thing about interfaces is that you can implement them to do any responsibility that you want so you could have a plant service that calls firebase that calls room retrofit graphql yada gada as long as you're using an interface and you override these two methods you can pull data from anywhere and that's why this interface is really important because let me create the next class to show you to provide put some code on the screen to explain this let's create a home view model so we can have a home view model that takes in a plant repository and extend view model so this parameter right here this is an interface so when my home view model starts up it's going to get some plant repository whatever you do decide to do to provide this right but by using an interface the home view model just knows how to get data and it doesn't care where that comes from so we could create like an in-memory version to use for now but if in two weeks the project manager comes to me and says hey we need to change this to use firebase i can create a firebase plant service make it use the same interface and just replace this at the call site and then my home view model remains completely unchanged so this is why it's really important to try and use interfaces for a lot of behavior specifically on your data layer so that this class remains entirely unchanged as long as the plant requests i need to make stay the same we don't need the viewmodel doesn't need to worry about where that data comes from so the next thing to talk about is um we mentioned that the view model was responsible for state management and i talked about state being important to help the view um be able to render the screen so the way i like to represent state is using a data class so let's create a data class called home view state and let's talk about what needs to be in our home view state so one way we can look at it with an app like this there's a lot of different ways that we could think about like this state right do we want to show loading for the whole screen do we want to show loading for each individual sections no i don't have like a spec for that so i don't know what the right answer is um i think for right now because we're not i think for right now what i'd actually like to do is not go into the nitty-gritty complicated state management let's actually start by just thinking about the state in terms of these themes right and then we can follow up and talk about loading and how to make it a little more interesting but i want to keep the scope as close to the topic of mvvm as possible without creating a too convoluted example so i know some of you may be thinking about loading but let's not jump there yet let's say that our home view state just needs to know plant themes so this will be a list of plant theme and we could say by default it's just an empty list and it has home garden items and so we could have this as a state and we could update it like maybe we add or remove items and then our screen would update as these change right this is all that we need to put in here for now so let's document this for anyone who finds it on github save this data class represents the view state for the home screen um all of this data whoops oops formatted in a way that the home screen can just take the information and display it so this should already be like everything we need for a plant theme what we put in here is stuff that the home screen just takes and is able to display it right so now we've created this class we need to discuss how the view model exposes that and something you may have heard of is live data but i believe now that android is telling people to move away from that in favor of something called a state flow which uses kotlin's flows and to create a state flow there's actually two lines we need here um a state flow that i just mentioned is something that is immutable so we first need some mutable way to manipulate our state so we can do that by creating a private variable we can prefix this with an underscore and call it view state this will be immutable state flow and needs an initial value and we can just give it the default constructor for home view state and then we need a public state flow that we can expose that someone can subscribe to and listen to so we'll create a public view state and that will be a state flow of home view state and then we can actually just give it the same value as view state so there's a fancy name for what this is called but basically the idea the reason we do this is because only the view model should be responsible for manipulating its own state so the mutable part we want to be private and then we but we need to expose a public state that anybody can listen to so it knows how to render the ui but we want that to be immutable they can't change this so that's why we have two lines here now we need to update that state with the actual data that we request so let's create those functions let's create one function in our viewmodel for each of the requests that we want to make let's make a private function um called fetch themes plan themes and here we can well what we want to do is call get the plant themes by doing plant repository.fetch themes and then we can say viewstate that value is equal to whatever our viewstate that value already is and then we're going to copy it and update the plant themes with what returned from the network response so and this is underlined because this is a suspension function because it could take a while to run this request so we're just going to take all this and we're going to wrap it in a viewmodelscope.launch that will create a code routine scoped to the viewmodel that will load that data so when we make this request to fetch themes we're going to update our state that will then update the state flow and then anyone who's listening to it will update we can think about this as this will cause the view to re-render and we haven't gotten to building that yet we'll do that very soon so let's make the other function that this screen needs to do fetch home garden items and this will actually be the same thing um plant repository that fetch home garden items and then update the uh state so the copy method is really nice method on data classes that says take all of the same information and then only manipulate any of the properties that we override so this is a good way to just update individual pieces so if we were to run these two calls in parallel which is what's gonna happen here um inside the init block you know if home garden items returns first then those would display first etc now in this app because we used it in memory service our data should show up almost instantly um but once i finish this initial labview vm setup we can look into sort of loading for each section and maybe play around with having them return to different intervals and see what stuff would look like um cool no other questions right now so that's for the home screen so far that's the view model so let's document what we just did um the home view model takes any request data um massages that data into a home view state that can be exposed by the view state flow so in order for the view to render the relevant information so that's the view model that is this part of our flowchart it's good to know that you know this was the exposed state that we mentioned and we didn't need to add any functions for like button clicks yet um because our home screen in this app doesn't really do any of that um but maybe again it's something we could look into like having our view model handle these check marks or something so let me know in chat or in slider if you have any questions on that um i'm gonna commit this code so far headings model and view model um because now uh if um henry is still here this is the interesting part of the stream which is using this inside jetpack compose um and there's a couple there's a couple considerations to make here specifically let's go look at our home screen composable so we have this is the entry point to our home screen that has a scaffold with the bottom bar and the home screen content um and there's kind of like a question here about how do we how do we get this how do we get this function to reference our viewmodel right we could pass in the viewmodel as a parameter we could look at requesting the view model right inside the function um i kind of looked up what other people have done and i've seen both approaches so it i like the coin dependency injection library and with coin i can actually request it from inside a composable function like this um another way i've seen it done though is passing it in uh through here and both pose a kind of interesting uh problem specifically when it comes to the preview functions so down here we have this preview that shows the home screen preview actually let me do a little split so you all can see the preview if it renders um but to talk through like hypothetically the problem we could run into that's um you know i can't from the preview function i can't create an instance of the viewmodel here right um so what do we do so here's the answer that i do have for that and if you look at the compose docs they'll talk about this but they'll have something called like the technical term they use for it is called state hoisting and that's basically creating two composable functions one that works with the v model and manages your state and the other one that just takes in whatever the current state is and knows how to render it so i would say let's try and build it that way so let's start by saying that we have home screen takes in a state which will be home view state right and then what we need to do is we need to pass this down and let's make this a default value for now just actually let's leave it and now we need to pass this down into all of our composable functions so that they can render stuff accordingly so like home screen content we're gonna need to update that to accept the state so let's go in here and we'll update this to take in a home view state i'm going to ignore some of the code that's already here because we've talked over it but do interrupt me if you have any questions about any of this compose code and i can go on a quick tangent um but here we have this theme section let's instead of passing in the whole state we could just pass in the current themes right so we can pass in state dot plant themes and for the home garden section we could do state that home garden items and then we'll of course need to update each of these so this will take a list of plant theme and now we can reference the themes from our state rather than have this be hard-coded to what we had before hope that makes sense i kind of went fast through this because for me personally i think that this is kind of just understanding standard kotlin code once we have the state we take it and we pass it down to all the functions that need it but do let me know if i can reiterate any of this but we'll do the same thing here we'll go into home garden section um and oh yeah i already happened to refactor because of the name change so now we have a home screen that can accept a home view state and render it but now you can see here if we go all the way down our preview function is giving me a lint warning if you can see that that's because we need to pass a state so let's create one for the preview um let's do home view state we can say plant themes our default plant themes we can still reference our hard coded lists and create the preview so let's do a refresh of the preview just to make sure this still works it looks like it did so to show one way we could oh ah i am going to so this is our actual main activity class this didn't compile because main activity is not passing in a home view state we will hook this up with the view model but for now to appease the compiler i'm just going to pass in a default home view state because i want to look here at the preview function first so i want to use this to verify that our preview still works and actually not just the preview but to verify that given some state this is able to render correctly and i don't know if it's hard to see i know my face will cut off some of it but it looks like this does render correctly and the way we could test that our previous state is being rendered correctly to be 100 sure is we could do something like um you know we could take like two items from home garden item and if we refresh now we should see this list on the bottom be just two items instead of however many and it is so this is a good way to use the preview to verify that it's rendering this state correctly so that's the first step is having a composable function scrolling back up to the top having a composable function that just takes some state red label one thank you for the follow i appreciate it a composable function that just i should move the alert box a composable function that just takes in the state but now we will need one that can work with the view model um now thinking about naming connect conventions here um ideally i would have like home screen be a function that takes in a view model so i'm going to rename this and it's not the best naming but it works for me in this context is i'm going to call this like home screen scaffold because that's the root thing here um i'm not going to rename the file we're just going to rename this function and so now what i'm going to do instead of that is create this a composable let's call this one home screen and here we can have this composable take in the home view model now within composable functions we have another state keyword to think about which is an actual class that is let me show you we can have a current state and we can get this by doing homeviewmodel.viewstate and then use this extension function called collect as state so what this will do is this gives me something called a state home view model um this is a compose class and what this oh is that on it oh so what this state is is it's a way for compose to keep track of some value and every time this value updates compose knows that it needs to re-render the screen so we can put that inside the home screen and say the naming and flow is so weird we can put this here and this is basically saying that every time the view state changes on the view model we want the home screen to re-render and that's great so this is where we could do something like check if we're loading to show a loading indicator or an error view here we're kind of always assuming success right now so we can take this and we can just then call home screen scaffold um current state dot value so now whenever our state updates the home screen will update so that's how we use a view model inside a composable function but the next step is figuring out how to get that view model inside of it and now this is something that i'm admittedly kind of still working through um i would love to blog about this so keep an eye out on my twitter for a real blog post but let me show you a quick solution for this app and i'll explain after i do it why it's not a good long-term solution because you can create a viewmodel here inside the activity but if the activity is managing all of these screens and i have a lot of view metals this is going to get ugly really fast what we can do to start is we could you know say home view model home view model and then we can actually do i think it's by view models and here we need to give it the view model factory because our review metal takes in some parameters so we can do object viewmodel factory viewmodelprovider.factory we need to override a create method this gets nest real fast for those of you who are familiar with dependency injection frameworks they will solve this but i'm keeping those out of this conversation for now but um once i get through explaining and using mvvm if we want to look at individual solutions i'm happy to do that um so if you have like fun questions exploratory questions hold on to them we're almost to the point where i'm happy to do that part of the stream we need to define the repository for this use case we're going to use a in memory plant repository or in memory plant service and now here we can do return home view mode plant repository is equal to repository and then we need to do as t whoops not that i'm going to suppress that for now so this is a view bottle factory this is a lot of code just to basically use this all that code basically boils down to this statement right here return a home view model so now what we can do is when we create our home screen we can create a home screen with that home view model so let me scroll up so we can hopefully see uh both of those pieces together so that's the a short solution is creating the view model inside your activity or fragment wherever you're using the compose view and then pass that view model in into your screen like that and then your screen will observe the state let's make this private now observe the state and it will update so let's put all that to the test let's run the app and make sure it restarts and that this worked yes that's really great question red label and um let's um let's do that next let's make sure this works and then i'll show you how we can do that um let's click in okay and that worked so there's our home screen so yeah that's a really good question um let's let's build that and give me just a second i'm gonna commit this code so far um heading to home screen do let me know in chat um or on the sliding link if any of you have questions about what we just did um but that's a really great question and yeah let's do that next because i think that's really important to to understand um because that's what we're gonna do in real applications right so let's think about for this example how we could um show something and let's let me show you a way that we could trick that here's what i'm going to do i'm going to do two things to build us a quick um reproducible case i'm going to go into in-memory plant service and when i'm fetching the themes i'm gonna delay for five seconds and i'm only gonna do this so i can simulate a loading time okay and i'm gonna go into main activity the other thing i'm gonna do and i'm going to change home screen to my default or my start destination so that when i want to run the app i always start at home screen and so let's look at the just those two changes and let's see what that does for our application and we'll probably see something interesting here so for a few seconds you'll notice there's no themes section at all and then it shows up and then it renders so i think uh a great example for red label is like what if i want to show a loading state while this is happening before i show the real data now if we want to get fancy we can show a loader just for this section what i want to do is let's build a loader for like the whole screen until we fetch both pieces of information and then we'll show the actual content i hope that sounds like a good example i think that will answer your question so let's build that the first step in that before compose think back to the architecture conversation how do we portray to the view that it needs to show loading well that responsibility would be inside home view state now one way i could do it is to make like a show loading property um on the data class itself we can also when dealing with view states use like derived properties and for this contrived example actually that's what i want to use so i talked before about uh it's a little confusing to think about well what if one of the plant loadings failed but let's assume they can't fail right one way we could know that if we need to show loading is if both of these lists are empty if both lists are empty that means we don't have information yet or i guess or if one of them is empty so we can create a variable here called show loading this will be a boolean and when we get this value this will return if plant themes that is empty or home garden items that is empty so that's how we will know on our home view state if we are loading or not so now the great question how do we show that well let's wait the question was one composable or another so let's create a composable um i thought i made oh god oh whoa whoa whoa i thought i made a live template on this thing for i was trying to make a private composable i thought i had that as a thing but sorry one thing i have noticed with this projector setup is that my trackpad is very sensitive this moves very fast um i apologize for the motion sickness i may have just called all caused all of you let's create a composable for home screen loader now i had to do this on another app and um i actually want to go find that code because um uh i can't remember how we did that we got a new follow studio jlva thank you for the follow um alright i am going to briefly copy and paste some code real quick nope that didn't work um i also have trouble pasting code inside um here what i want to do for the home screen loader i first want to make a box that takes up the whole screen and i want to do that because i want the loader to appear in the middle so we'll create a box that takes up the whole screen and then we'll put in a circular progress indicator and we'll give that a modifier as well um we wanted to wrap content size and then we wanted to align to the center of the screen ah so that's how we create our loader sorry that was not smooth typing all that out between like all the highlighting and everything please forgive me um but now we've got a great question we know how to create a loader so now we need to know do we show the loader do we show the content well one way we can do that is actually right here where right now we're showing the content let's copy this oops ah and we can actually just put an if statement right here so we could say if state that show loading we put home screen loader else home screen content now i think actually to be consistent i should pass in the padding values to the loader so that the loader renders correctly for those of you who missed that section and you're wondering what padding values is um here we're using a scaffold yeah please check it out on youtube i'll upload that i think twitch tells me i have to wait like 24 hours but it will be up there by this weekend for sure um when we're using a scaffold with a bottom bar um this bottom bar creates like padding that we need to think about so this lambda gives us the padding values um without this our loader would actually be like bottom to top but i want the loader to be considered from sort of top of this bar to the top of the screen so we'll accept those padding values so we can use those we could use that on the on the box we'll say okay so let's refresh um red label i hope this answers your question um you can really think of i mean composables are just functions so um it can really boil down to just using like conditional logic to determine whether or not to show something you can use an if statement like this you can use a when label whatever works for you a for loop even you could use a for loop to populate a column or a row it will be on twitch yes but twitch gets rid of them after a certain time so now let's run this and we should see look there's a loader it's very subtle but it's there and then after five seconds we did it we got the loader so that's how we can use the viewstate to conditionally show or hide some logic and if you use a viewstate for not even just for the full screen but if you used it for like an individual item you can use that to style text colors you can use it to change a font size whatever you may need to do i hope that answered the question in a good way um i will even i will close this real quick and i'll run it again if someone wants to see it yeah of course thank you for that question cool so that's i'm checking the other site real quick if anyone have any questions doesn't look like it so that was yeah that's i'm happy to keep going but this is a good kind of pausing point that's a great overview of the mvvm architecture and how it works and compose apps um one thing i really like and i want to reiterate from the beginning um that walkthrough was in case anybody hadn't really seen it before but for those of you who have existing apps and you're learning compose and you're thinking about how to add this to your future projects there's a good chance you already have an android x view model that exposes view state either as live data or as a state flow and this goes to show that your work to add that to compose is putting the compose work aside i'm going to say one line right it all boils down to this taking a view state converting it to a composed state and i'm using that to render you don't need to change anything about your app architecture to work with compose and even if you're using a architecture library something like mavericks from airbnb i know that they're actively working on compose tooling for their libraries so that you should be able to take whatever architecture you have and add it with compose and so there was really good question too about like well how do we use like room and retrofit with compose and really the answer is like it's not different um the work for creating a data layer with room or with retrofit you know putting that inside of an interface that we talked about that doesn't touch the compose code at all um so all of the knowledge you have for data requests data management you don't need to change any of that for compose the only thing that updates slightly is obviously the view part the ui framework is all different and a little bit about hooking up the view model to that view um but a lot of the other code that we have in our applications will remain unchanged which is really exciting so you know i think for now um i'll open it up to see if anyone in chat has like an interesting challenge yeah challenge for me or challenge for this like if we want to try and add a little feature uh a random thing someone might be interested in learning about um and i what was that idea i had i thought i had one um i can't remember now inject me metal using hill do you want to do you want to see if we can pull that off um i think hilt is really popular um would be good to know how hilt works with compose so i asked the question i guess i gotta i gotta oblige right um i let's find it remodel tilt jetpack let's see if we can find some docks on this already i think that we can ah yes i think i tried this before so this is actually a um uh this let out but i think it gets worse when i highlight sorry i think this is the thing that i was looking at before so um oh actually interesting i think that i misled everyone with my factory method earlier this sounds like it has nothing to do with hilt yet to use the v-mount oh no i guess i still need the factory but this is showing that i could create a view model inside of the composable um rather than inside the activity let's try this first just because i'm curious so to do this we need the lifecycle viewmodel compose artifact so let's get that so i don't think we have that i alpha 4. okay let's copy this let's add that real quick um so we're going to add this life cycle view model compose artifact and we are going to take the view model code that we put inside our activity and we're going to shift that to be inside the home screen composable and hope that it works because i personally would say that i i am i prefer that i don't want i would prefer to have the composable function for the screen be the one who creates the view metal because it keeps these other classes more slim right and we don't need to have them worrying about creating view models when only this one function right here cares ah i forgot so one bug i have in this uh projector stuff is if i do command x to cut something it doesn't actually um oh my god it doesn't actually copy it to the keyboard command c does work but command x doesn't copy it to the keyboard i think this is equal in that hmm oh okay i don't know if i need to all right let's i'm just looking at the function signature so we need to define the factory as its own see why didn't that work command c what the heck it won't paste the code i don't know why so this is a projector bug we can deal with that later i am just going to type this all out and yes i am using projector and i'm finding a handful of weird issues throughout the stream but it's mostly going well so now we can say home view model um whoops look at the equals view model um we need to give it a key in the factory the key can be null the factory is the one we just created binary thank you for the follow i really appreciate it um close that preview okay so this function is a activity lifecycle compose function let's try that let's run that and let's see if that works and that's another way so if this does work this is a good step in not having to pass in the view model to the screen but letting the screen create the view model that it needs this would definitely be my preference um but looking at hilt would be nice and probably makes it even even simpler it looks like that did work nice good suggestions let's commit that but then i also i guess if we're looking at hilt we can also look at that next or at least look at the docs and decide if i want to go down the rabbit hole so we've looked at hilp four months ago um it looks like the only thing that um hilt would give us um over what we already did is that with the annotations of like a help view model and add inject we would get the information and then we could just call equals v model and the nice thing about this is we don't need to create the factory ourselves like we just did hilt would do all of that magic behind the scenes um so that would thankfully trim down some code um but i think the time it would take to set up hilt is probably not worth diving into uh but for anyone interested i will share those docs if you use hilt in your apps um that's good to know but that was a good question though i appreciate it and i'm glad that i looked into it so i could find this because now main activity is still very slim um and it's just the home screen that gets the view model so what are other state i'm wondering if there's other state tricks that we could do all um here we go i read that you can store the state object in memory by using the remember composable right even retrieve the value after process death with remember savable interesting question is would it make sense to build an app around this and just get rid of the view model completely no that's a great i know we were talking about mbvm and i was just wondering no that's a great question and i'm kind of at the point in the stream where i'm happy to do this sort of ama thing so anything's on the table if you want to switch away from compose happy to talk about anything that was a good question um even retrieve the value after process death with remember savable would it make sense to build an app around this and just get rid of the view model completely um so i'm not familiar with like the remember savable i have seen the remember um and i'm curious how that works i mean that probably helps over like um uh configuration changes actually that would be a fun thing oops that's not what i wanted to hit that would be a fun thing to test on the loading screen like does this work right when we switch orientation it looks like it does um cool i just wanted to test that that worked um the reason i'm hesitating i kind of want to say no and more specifically because the view model does a little more than just state management right like the view model it's also making like network requests and the status of like a network request is not persistent in like remember savable at least not that i'm aware of um so like you still want a view model that survives like configuration changes so that any processes that it's running would keep running for example um that's a good question i don't know i'm sure the compose team built it for a reason so there might be a use i'm inclined to believe that there is a use case where it is preferable over a view model or maybe it's good enough and easier than a view model but i unfortunately don't know what that is um but i'll think about that and uh maybe i will try to get the answer for you that's a really good question i appreciate it i'm sorry i don't have a better answer right now um it's kind of like off topic for the stream so far but another thing remember we'll prevent recomposition interesting yeah so that's a good it's a good point um about the recomposition so that's a portion of compose that i want to learn more about uh specifically the like recomposition right because um the way we have this app built is we get the current state and then we call this home screen scaffold with our current state well what happens if we wanted to change this and let's say only the theme section changed i don't necessarily want to recompose the whole ui i only want to recompose a portion of it and i think that under the hood compose does some work to be smart enough to do that but i don't know if the way i built it plays into that i also don't know how to get that answer that is a thing about compose that i still need to learn about um throwing it back in my brain has got another blog post idea to understand that recomposition if any of you are ever interested in um uh diving in to compose at a very technical level like looking at the compose compiler and understanding how compose works itself um a person named leland richardson they also um i think this is their handle well i'm a stalker they also like to stream on twitch and they work at google on the jetpack compose team and they usually stream on twitch and they dive into like the compose compiler they can be really fascinated so definitely check them out if you're interested in uh doing a deeper dive into some of the stuff so yeah i guess i'm happy to keep chatting ask random questions i don't know if there's other stuff to add here um we can if people are interested and want to keep hanging out one thing that i have been wanting to explore with compose is input validation um specifically around like if i have like some text input and i want to like show an error message or something i'm like what does that look like um and i looked at the jetpack composed samples and they do something that is like like galaxy brain uh text state management but i was really fascinated by it um if y'all are interested we don't have to build it but we could talk about it i could pull up the samples and show you what i just meant there hopefully i'm checking the sliding link no nothing yet oh wait no okay i just realized i was on the wrong screen for the slider the whole time but no one has sent a question so that's good um if we were to look at jet chat for example let me find the f um there's a file oh so they have this class called text field state and um this is really fascinating so they created this text field state class where you pass in a lambda for testing if the text is valid and another one for seeing if there's like an error and then it keeps the text as immutable state keeps information about whether or not it's focused or whether you should display errors and then it updates on focus it updates showing errors but it like it updates in real time to know like do i have an error do i need to display it i guess we'd have to look at the call site but i spent a little bit of time diving into the jetpack and post samples oh you can't read any of this i'm just talking out loud i really gotta get better at that i'm so sorry um yeah it's very like interesting to dive into their code the one thing that i love google samples and one criticism i will have and i also have this issue but i and i know i need to work on it but i try really hard and like you saw me do this sometime on stream a few times on stream is like you comments like this even if it's just a paragraph explaining what that file is for goes a really long way for people who are trying to use your public code as guidance like when we look at this jetpack and post sample like they don't really give us anything like this comment here was the text field ever focused i guess that's helpful because i don't know what this means um but there's no other comments in here and if i was trying to understand how this worked i'd really have to like sit down and reverse engineer all of it and i know that some of the work i've done also falls under that category so i'm not trying to put myself on a pedestal here i'm really saying it as something that i as an individual need to work on but that all of us collectively uh can work on i think that's really important i think it goes a really long way documentation's something that's really important to me and i try to always focus on it but i think maybe in my next stream we could focus just around text then i think it'd be like a good stream blog post um i also have this really great idea of a short youtube video i want to make and how i on this topic and how i go through the jetpack compose code um like me personally how i look at it how i deal with that sort of overwhelmingness of looking at source code to understand how stuff works because i think people will often um you know if we go like here i think often what might happen is um people might be like i want to understand how scaffold works so they do like a little command click right here and then this is very overwhelming this is like this is a lot and if we didn't write this code it's very hard to understand it and um you know and then there's all these docs like i definitely get that uh so i thought about doing a short video on like how i approach that and how i find that helpful huh oh good question hallie written on one thing i'm wondering after watching some of your streams why does jetpack seem so powerful compared to non android kotlin ui dsl also why is this still scrolling i'm not touching my trackpad anymore um oh i think this is tangent i think it's because this file is so large that projector doesn't handle scrolling well in super large files um so we're gonna close oh god okay we're good i think um so i have not used any other um oh man i really screwed up projector here it's just doing its own magic i have not used any other kotlin ui dsls i'm sure maybe what you're thinking of is like um what was that one called anko is that the one um oh it's booked by kotlin i didn't realize that oh they archived it um so i this is a good question about like why jet packs seem so powerful compared to those i don't know if this answer is correct but my technical hunch is that like compose as i understand it is it's kind of rebuilding the ui framework from the ground up like we all know that all of the views that we deal with now even new ones like constraint layout motion layout they ultimately bubble back up to the god classview.java right like they all use the same old ecosystem but compose is brand new and my understanding of like anko for example was a dsl wrapper around that existing ui framework so when you look at something like anko the way i would think about it as like maybe not just syntactic sugar but that's probably why it doesn't feel more powerful because at the end of the day it's the same tool that we're writing an xml just a different approach but compose is different right like compose it's not the same tool like it is like a whole new ui framework and it was built with a lot of these new capabilities in mind making motion easier making animation easier you know making modification and styling easier neocompose was built to be able to support like dynamic styling but if anka really is just a wrapper around like existing tools then dynamic styling's still not a thing so i think that's my element kind of like a guess as to why those tools don't feel more powerful because i don't want to say because they're not because kotlin is powerful but at the end of the day like it's using the same tool so that's probably why i never felt like it was giving you something new but that's what compose actually is giving us that's my understanding i would love to hear anyone who has like a different opinion or experience with that but i kind of like i love answering all questions i know some people love to do like amas on stream i don't know if people would be interested in that like doing a sort of just chatting talk about my experience as an android developer if y'all are interested in that i'd love to do one also happy to do it now like i said i don't know if there's more to code for tonight but i'm happy to answer any and all random questions people have about anything android i guess i'll wait a little bit then when there are no more questions we can sign off after this i'm gonna go enjoy season three of rocket league new new update hit last night although i have had like an issue with the network on my playstation 4. can't figure it out but every time i play rocket league i've really been lag lately even though we're internet just fine also if there's anyone in chat who has been here for the whole stream i want to know were there ever any hiccups because streamlabs is still telling me that i have zero percent dropped frames um and that is like incredible um and i'm really glad that i set a projector if it's working well i didn't know that google was going rust on aosp if prince is still here i'm sure that would fascinate him my roommate prince loves rust awesome i'm so glad i don't know when i'll get to it but i do plan to release an explanation on how i set up projector um so i think one of the so there's let me we could talk about projector real quick um so interesting am i is that my stream or is that a twitch setting on your end i never actually set i don't know if i have that setting on my end but um another question before we go here i make google i o predictions i don't have any yet um i i think io is too soon to say that like they'll announce jetpack compose stable but um interesting okay thanks for pointing that out i'll look into that maybe there's more i can do um i haven't looked into a lot of streaming stuff um but that's good to know and i'll see if i can improve that um yeah i don't i don't have any i o predictions right now that's a good good point um i think io is too soon yeah i think io is too soon for there to be like um and they can post stuff same thing with android 12 it's possible that like actually even with android 12 i don't think they'll give us like a launch date i don't think we get that until the fall usually i have no idea this is a good question i mean also part of it is like i mean not just because io is virtual but i use virtual because there's been a lot going on in the world so i don't know if like google has been able to make fancy new products or tooling like they normally would um but i don't know maybe that would be the biggest surprise maybe they'll announce something that no one was ready for i have no idea i hadn't even thought about it honestly um i hope that next year we could all meet in person i have actually never been to a google i o last year was going to be another chat app yeah exactly um last year was going to be my first um google i o and then well you all know some of the sad but i would love to see it one day you're at 2019 how was it don't say that it won't be the last one oh god don't say that yeah there were a lot of conferences i was supposed to go to last year um i oh uh kotlin comp i was going to go to that for the first time i was going to go to android makers in paris i am really impressed by a number of conferences how they were able to move to a virtual solution and it actually worked really well i spoke at a couple virtual events yeah i would love to see the googleplex like my bucket list item is to see the android statues like i just i really really want to see those i've been fascinated with them sort of ever since i've been an android developer um so those of you here while i'm thinking about it because i had the thought and i wanted to get like chat input on this so this is a really great post by uh walking on um setting up jetbrains projector and i'll give you the tldr which is um i'm in the u.s yeah but i'm on the other coast of california so i can't go anytime but it is a little easier for me of course but if i was on the same coast you know it'd be easier but the tldr on setting up projector is basically you create a virtual machine or some cloud instance you install android studio there you install projector and then you run projector and it will render your ide at some endpoint at whatever the ip address is on subport and then you can view it so i found this helpful but something i personally struggled with was like you can use any tool for a vm right google cloud aws etc but i personally as a mobile developer i didn't know anything about that so the hardest part in all of this was me figuring out how to set up google cloud so i'm actually wondering if it's worth it to do like a youtube video where the first five to ten minutes actually walk through that like first how do you set up a vm and then how do you set a projector on that vm because i wonder if there's other android developers like me um who don't know anything about setting up a vm i'm like sure just focusing on the projector part would be helpful but maybe not enough um so there's two ways to access projector to your question do you access it using the browser you can uh the reason i didn't do that is because they haven't yet set up like credentials on mine so i didn't want the ip address to be visible on the stream but you can access it through the browser or i'm using a native uh client that jetbrains built um and when this client starts up i put the ip address in there and then launch it um it's my understanding that one of the benefits of the native client would be that they can proxy uh keyboard shortcuts better um but like instead of the browser intercepting those keyboard shortcuts but um i've had a couple issues with keyboard shortcuts today can you also run emulators there so the vm that i set up doesn't support emulators um i i think the short answer is android stadium i think the short answer is no to can you run emulators partially well so the vm that i set up doesn't support it's not powerful enough like i tried to create an emulator and like the avv manager or whatever and i couldn't create one because it needs like some hardware specifications um i also don't know even though there's like this emulator window i don't know if android studio would be able to i don't know if projector itself can render the emulator window um maybe someday or maybe someone could figure that out the solution i've used is i'm able to connect my device basically if you use ssh at a certain port specifically the port that's also running adb then you can connect the two devices so that's how i'm able to run a debug onto my own phone even though this is running on a virtual machine i don't know like if you had your own cloud setup like if you could use an emulator like if the machine supported it but i still think you would run into some issues i just want to say i appreciate the two of you for hanging out and i am also like slightly fascinated that the people who are most active in my chat like aren't here on the east coast like the time zones right now are very wild because tracks it's like what like three four in the morning and sue has like could i have lunch soon or something like that and it's evening for me yeah well so um i can actually it won't expose uh any information on this script uh so let me share this with y'all um let me walk through my setup briefly i'm pretty sure yeah okay so this doesn't give any information so here's a script i have in my computer that starts this so wow i appreciate all of you like night owls hanging out with me um i know i mean i guess even though it's like a standard time for other east coasters it is also like after work so i'm sure people are tired they haven't eaten yet so that's probably why but i need to look into either more streaming slots or maybe try some different tools but that's why i'm really glad i could put the videos up on youtube um so here's a script i have in my machine to start a projector and i'll just kind of walk through why this works so uh one thing is um i don't know if you absolutely need this but it was recommended from walking to kill the adb server before you connect your devices and then start it up again make sure everything's there then i start my virtual machine if it's not already running and then i ssh into it and i use this ssh flag to connect on port 5037 this is where adb runs by default so this is this is basically the magic of connecting adb on that machine and then once i get into that machine i run a script that's on the machine and that script basically all this does is it runs like project run android studio and then once that's all done i can get the ip address plug it into the client and ta-da we have we have our ide so i will definitely um i would definitely love to uh share that setup you know uh definitely check out uh joaquim's post that i posted in the chat uh they are definitely the trailblazer here um they even show how they like are able to open up android studio on their phone like anywhere they can render a browser can render um android studio you could run it on an ipad but very cool they're definitely the trailblazer on there but i always find it helpful to sort of provide an individual perspective and maybe talk about like some hiccups that i found in this process as well um trying to move them out of my machine same as projector oh no so this um this screen that you're seeing right here is using something called screen copy and it's basically rendering my pixel phone right on the um it basically yeah it's called screen copy and that's effectively what it does and i believe i could start an emulator yeah like visor i believe i could start an emulator and do the same trick because it's even an emulator uses adb i haven't tried but that would be interesting um another thing that's fascinating is like well it's anything that's adb right so actually one day i set up wireless debugging with adb and so that i was able to take i was able to run android studio in the cloud and have that cloud instance running to fight run an apk on my phone over wireless abb like the future is crazy that was so cool just that alone i was super excited about and after having built something all night you know projector's pretty good had a couple little hiccups uh things i might go report other issue tracker but pretty interesting yeah wyola say today is great my drink is gone now i can finish my soda oh um the secret is do not disturb there are plenty of notifications but um not that i ever worry about it but like i feel like the one time that i stream my phone and i'm not paying attention is when i'm gonna a friend is gonna send me an inappropriate meme or something and i just don't wanna set myself up for that so do not disturb and i love i don't remember when they switched it but i love the recent versions of android where do not disturb actually hides all notifications um way back when it was like do not disturb it only got rid of like the vibration or the alert sound but they were still in the notification tray i like that i do not disturb they're just like gone until you press this and then they come back you know we're almost at the two hour mark maybe i'll hang out for eight more minutes while we have questions and then at the two hour mark we'd call it a night i um yeah of course thank you for coming uh thanks again to some of you who are sub to the channel i know i've talked about um i want to do a thing where um the revenue from twitch excuse me the revenue from twitch when i get it i want to donate it to some tech organization i haven't figured out where i'm open to suggestions um but with that uh if you see it on other channels when you sub to a channel you can get like a little badge next to your name like sue says the cool founder badge that says like first but streams can have customized badges for their subscribers and i recently commissioned some i'm hoping to have them this week so next week i can share off and tell you what they were i'm actually really excited to share the theme but uh yeah prematurely sharing it i don't know if i'll be ready next week but i'm excited actually i think there aren't other questions that's late for y'all we can call a night thank you again for stopping by i really appreciate it i'll tweet out when this video is live let's change this back to welcome and as always let me know if you have suggestions on um stream ideas this one was something i winged together hopefully it was good for like winging this together in a couple hours um but one more question last one for the night tools like compose before being released to the public are somehow enforced inside your teams or it's up to you if you want to test it good question tracks let me answer that before you go if you don't mind um so it's usually individual teams that decide if they want to explore things before they're released so all of the compose work that i've done has been on streams on my own project i'm not currently using it at my like work job although because i'm loving it so fast i'm actually tempted to try it for my next project but usually it's within teams a lot of companies tend to i feel like a lot of beta testing happens at the individual level i think a lot of companies are afraid to buy in because of the fact that it's not stable and if something breaks that usually means like money is involved like if your app breaks and you lose revenue that's a bad thing if i'm building something on stream and it breaks then like no one's hurt you know um but it's up to the team right if a team is interested in taking that risk then they can do that and you know i have a lot of respect for teams and individuals who are willing to do that because without people who are willing to test stuff and provide feedback we would never have these tools to begin with um you know i'm glad i'm testing out components but sometimes i feel bad that i haven't taken this taken the handful of issues i've had and like reported them back to google because those sorts of things are actually what really drive things forward i've done that a few times with kotlin actually it's very rewarding to see things introduced into the language that like i had struggled with i was cool i helped move this forward it's very rewarding feeling um yeah thanks for the question y'all follow me on twitter hit me up there or um i know one of you has reached out to me on linkedin anywhere you want to reach me anytime you have questions i'm always happy to chat with all of you thanks again have a good night everyone
Info
Channel: Adam McNeilly
Views: 6,014
Rating: 4.9425836 out of 5
Keywords: games, twitch
Id: XJoVnkVL6i8
Channel Id: undefined
Length: 112min 10sec (6730 seconds)
Published: Fri Apr 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.