Evolving Compose Multiplatform on iOS and Beyond | Sebastian Aigner

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey everybody Welcome uh to today's session on evolving compos multiplatform on iOS and Beyond uh my name is Sebastian you may have seen me earlier today uh or in some other contexts and I'm very excited um to spend the next 45 minutes or so um giving you a little Whirlwind tour of all the changes that we've made um in compos multiplatform ever since we last talked about it because it was actually just one year ago where we stood on stage and we first talked about compos multiplatform uh on iOS and some of the other platforms for the very first time um and of course this was a really exciting time for us because with compos multiplatform we really managed to take the cotland m mul platform story to its natural conclusion right rather than just being able to share business logic with hotland multiplatform um you are now also able to share your UI elements not having to do them uh over and over again but instead um being able to share them while still using the platform capabilities even on the UI layer and of course uh it's a pretty exciting time time right now because um the stabilization Journey for composed multiplatform is in full swing on Android when you using compos multiplatform um that just decomposes no pun intended right into jetpack compos so here that's naturally already stable on desktop we've been stable for a whole while and if you've ever used Jeet brain's toolbox um then you have actually used um a composed multiplatform application on desktop yourself and as you saw earlier today um we have promoted the iOS Target for composed multiplatform to Beta since just earlier today and with the compose multiplatform 1610 release and we've promoted the web Target to Alpha so it's a great time to kind of see what has happened since we last checked in with compos multiplatform so today I want to take a look both at some of the iOS specific changes that we've made but also talk about the general common apis that we've introduced that are actually available on all composed multiplatform targets we really hope that those are going to be very useful for you so last time we went up on stage we were very upfront about the fact that there was still a lot of work to be done and across multiple um sectors right from things like how you actually interact with the application um all the way to how you implement navigation how text selection and input works and of course also topics like accessibility now I don't have a lot of slides nor do I have a lot of transitions but this one I think is my favorite since the last time we spoke about it we have made progress in literally every single one of these areas we have either fully implemented the functionality that we set out to do we H or we have provided something that has made significant progress and that you can already use or we have at least an experimental version that you can try out and that we will continue stabilizing over the coming future now when I showed this slide uh to a colleague um he rightfully noted that this does not actually reflect what happened this is closer to what it actually looks like the vast majority of things are just done now which is very exciting and a couple of other things are still a work in progress we can start out with subjects like accessibility now iOS has a very strong accessibility system with voice over that doesn't just include text to speech it also includes a full gesture navigation system that's specifically designed with accessibility in mind with the newest versions of composed multiplatform out of the box your components behave correctly ly um when it comes to the accessibility hierarchies um given that you provide content descriptions for um your images for example those also show up correctly um if you look at them using the accessibility inspector or just enable voice over on your device um so all of these features are actually available out of the box we've also revamped scroll physics so that they essentially exactly mirror the scroll physics that iOS users are used to including overscroll and spring physics which just provides you with an even more native feel when you're using composed multiplatform and we've also introduced new interop functionality uh for example if you're mixing Swift UI and compose then even if your compose part only takes a small fraction of the screen if you have for example popups or dialogues those can still stretch through the entirety of the screen uh by being rendered on an entirely separate layer we are also making a whole bunch of progress here and we made a bunch of progress to make sure that you can use the entire real estate um that the screen of I devices provide um with the uh new changes to insets and cutouts so what you can essentially just do is you can go into the Swift Code that calls your um compose uh code for the first time you can turn off the safe areas to make sure that it actually renders across the entire screen and then from there you can use the common Windows insets API to make sure that all your elements are placed correctly on the screen um if you've done Android uh development with compost before then you will have seen these window insets padding functions before for example you could use system bars but we've actually ported an entire Library of these to make sure that they're also available in common code which means your applications can look great whether they're in landscape whether they're in portrait mode um and whether that device has like an island a magic island or a notch or whatever Apple might come up with next Cody's face is of course optional we also introduced a new common UI testing API uh which allows you to now write UI tests once and then execute them across all the targets you have with composed multiplatform what this could look like for example here we have a tiny composable all that does is put some text on the screen um that is supposed to be prefixed with info I am not very good at typing um but rather than relying on uh gratzi or some other grammar tool um it's probably makes more sense to actually write a test to ensure that this thing actually does well what it's supposed to so in this casee for example we could just run a compose UI test um that takes a Lambda here we can set up a bunch of composes in our case that would be our uh our info composable because this is a very simple one I'm just injecting a test tag here uh to make sure that I can still I still have an opportunity of easily uh finding it but of course there's also other ways of traversing the composed hierarchy and then I can just write an assertion to make sure that the text actually contains the substring info when you run this for example in Fleet but wherever uh you will of course then get a um a failed test and you will see exactly what it is that you've done wrong but we are also making a whole bunch of other libraries multiplatform um that includes common resources it's life cycles and view models and it's also navigation and all of these are available either as stable with resources or as experimental with life cycle view models and navigation for you to try going forward we can first take a brief look here at resources um essentially what we're providing you here is something that once again you are most likely already familiar with we are providing you typesafe accesses um that you can just access using the res object rather than the R class that you might be used to from Android and then in your common main source set you can just throw in a composer Resources directory and put your files in the appropriate uh subdirectory like drawables files fonts and values for Strings let's actually take a brief look what that looks like in reality so I can just hop on over here I am in jet brains Fleet um I'm just in a small little demo project here let me make sure I close this um we are of of course um in the common main folder so we are entirely in platform independent code here and I've made sure thanks to the wonderful pre-flight checks that my uh development setup is actually set up correctly so let's hop on in here and let me also make sure that I have my other files ready over here and here we just have a very small application I can actually just briefly run um the preview here to give us a bit of an idea of what this code actually does as you can tell very little um not very beautiful what always makes things a lot nicer is when you throw in some graphics or if the text is maybe slightly more descriptive um than just some text so we can do exactly this um we can hop on over into our common main folder here and let me just copy a file um we can go into common main uh and we can grab ourselves a compos Resources directory and in here we could create our drawable subdirectory I'll just throw in a file I guess I did not copy that correctly give me two seconds there we go okay so I've moved this in here now um so what I should be able to do is rather than just draw a box is I should be able to just draw an image um this one would use a painter resource and then I can use this res object um we're looking at a drawable and I added a banner here and of course we'll also provide some content description and within a couple of seconds we can see hey it's cin conf one of the things that you probably thank you very much everyone loves calling one of the things that you probably noticed here was that I didn't actually have to do any like reloads or anything like this that's because um Fleet does have integration uh for composed resources so it actually detects the moment I move new files in here um it automatically regenerates all these typesafe accessors otherwise um if you're using a different IDE you could just use the uh generate compose res class Gradle task that would do the exact same thing here we just get a little extra convenience okay some text is still a little non-descript so maybe we can also throw something in here rather than just having drawables will'll also have a values directory now I do have some strings already prepared here just so that we're not just looking at a single lonely string um so let me just create my strings.xml over here uh this is just from a another samp project um but we can of course also create our own um string here this follows the same conventions that have already been established in Android development so for example here we could do our conference description just close this for a moment here um and we could for example say well we are looking at some sort of conference and we can then hopefully inject this part so moving back over here um we can just grab our elves actually the string resource um and in our case that would be res string uh I believe I called it conference description is that what I called it no I got it but thank you appreciate it so once again looking at this well without a placeholder I don't think we're currently at a percent one1 s conference so maybe this is a cotlin conference just have this reload for a second and heybe that looks a little bit better some might even argue that this is now a multiplatform conference who knows and of course we can see that one as well now of course you can also um actually parameterize uh your resources right so rather than just having some values here what I could do is I could throw in another uh dire called values de I'm naturally a German speaker so this is the only translation I could reasonably create um I could just throw all of my resources into this directory um and could then start translating these I guess what I can also just do is just ask AI assistant and if the conference Wi-Fi works we'll see we'll see oh no well I guess that's my fault isn't it should I do the hot spot or should I be I can't even see the calling one there we go let's try that one more time there we go Su looks good cupcakes looks good in cupcake looks good the a conference also is perfectly formulated look at that so of course uh my uh entire setup that I have here on my desktop uh is actually um in English but if you take a look here and you look at the be and a couple of other great uh names that I have here on my iPhone emulator you'll notice that that is indeed in German so the moment I actually run this application on this I device so suspenseful every single time it is indeed in multiplatform [Music] conference wonderful uh I don't want to stretch the uh the demo on this part too much but I do also just want to uh note that you can also use plurals um and AI assistant does write these correctly does it no it actually doesn't in conference doesn't well you know I guess we still have the upper hand over the robots just for a little longer but of course the apis exist and you can absolutely use those great wonderful so as I said um you actually have a bunch of different ways that you can uh specify what your resources should look like uh you can do that by type you can do that by um language or region uh you can also throw in the theme um as well as the density sure why my cursor keeps on sticking around there but that's okay all right for example if you look at a German dark mode drawable that is what I would imagine that would look like has gone through great user testing um we also support multimodule resources if you're on cin 2.0 plus um which means you can create libraries or you can create separate modules for your applications um and you can throw resources in there and they will also resolve correctly so as somebody uh who's a big fan of throwing a bunch of different emojis into like all of my slides and like all of my applications I do hope that we'll see a lot of different Emoji flavors maybe open emoji and so on packaged and ready for use uh in composed multiplatform okay so let's continue and let's talk a little bit more um about our life cycle implementations um first of all the question maybe arises why do we even need a crossplatform life cycle well generally a life cycle life cycle abstractions are really useful because they do help you build more robust applications why because if you or your um code can understand in what phase of the life cyle your application is you can stop doing unnecessary work you can avoid doing these kind of things so this is one of the typical charts that you might be familiar with if you're a mobile developer you have a bunch of different states and then you have a bunch of different state transitions uh on Android those are just um the things that you would get out of the box uh we have actually gone ahead and we have mapped the iOS life cycle um events onto this same life cycle model so things like view will appear um will enter foreground and background as well as view to disapp here um we have just kind of essentially hooked up together here again these are actually common so they are usable not just on iOS um we also have implementations for web there it's particularly easy because the life cycle of something running in the browser is usually it's either there or it's not um on desktop we also have a couple of mappings we're not going to look into those uh too closely right now but they're all available in the cotland multiplatform development documentation so let's have a quick look at a tiny little demo of this one I'll just be a very quick one so we will just quickly open up my life cycle app over here and we can take a peek inside this application does uh very little um I've added a life cycle logger which is a uh custom composable that I've created all that does is it looks at the current life cycle events and the current life cycle State and just prints that to the console um and the other thing that I have in my life cycle app is I have this cold flow that I can now in common code collect using collect as state with life cycle um I know that there was a bunch of like Reddit threads and so on uh for people asking like hey when should I use collect uh as state and when should I use collect asate with life cycle and the like common wisdom was always well if you're doing multiplatform you can't do collect state with life cycle we've finally caught up here um so that wisdom no longer holds okay so we can actually take a brief look here you can see that as the application starts um we get into the resumed State um by going through oncreate on start and then on resume and you can see that our little um collect estate with life cycle is indeed running now as I move into the app switcher um we get an on pause putting us into the started State uh if I just were to go back we just go straight back into being resumed and of course if I just navigate out of the application back to my home screen um I get an onstop which puts me in created um by default uh when you're back in the created state things like collect as state with life cycle um will cease its operation um so you can actually adjust this just by kind of like having a look here at the overload you can see that there's a Min active state that one determines um when the collection should still happen but it would now be reasonable to assume that as we navigate back into our application the flow gets collected again from the beginning so it starts again from the start cool great so with that what we have seen or the main takeaway here is look at that we have a collect state with life cycle as common code now woo [Applause] cool so now let's talk a little bit about view models um why do we need view models well uh of course I don't want to be super prescriptive here if you have other architectures that are not mvvm you are welcome to do those um I I have uh no horse in this race but they are indeed a very wellestablished stolder abstraction um for a lot of mobile developers um they obviously encourage unidirectional data flow um where you have uh your UI emit events into your uh view model and then that view model updating internally and of course they very naturally integrate with the life cycle abstractions that we've seen prior plus they play a special role on Android with the whole survival of configuration changes activity Recreation fortunately you can rotate an i device and nothing bad happens so we don't actually have to care about that one if we're working in common code I suppose you can also rotate a web browser and nothing will happen I don't know what that would look like in practice so we're actually um publishing these as two different artifacts we have the life cycle uh view model uh under the or jet brains coordinates and that's actually a common view model that is composed independent right so that's just the view model abstraction that could also be used without using compos multiplatform and then we also provide life cycle view model compose and that provides you with things uh that allow you for example to scope a view model to a nav graph or just to instantiate it using these kind of factory functions okay so let's actually take a look at what that might look like in practice um so I'll just grab myself my view model demo application here and we can actually just take a quick look on paper this is once again a very simple application uh it just has three buttons um for your current mood that I guess you could log for example happy neutral and sad and then you probably want to store that somewhere unfortunately that currently doesn't do anything and this is maybe one of the classic cases where you would want to Outsource this change mood logic as well as this kind kind of counter that uh indicates how many mood changes you've stored um You probably Outsource that into a view model so let's actually have a look here and move over to my very empty mood view model um we can just once again start with a little bit of a scaffold so we'll just do a view model with a state flow of change count uh and a we'll call this we'll we'll Implement that ourselves and a too store change function that looks pretty good hey look at that and once again here you can see the power uh of composed multiplatform uh shine again um because once again I mean these apis were out there on Android for a whole while so all those fancy llms they kind of know how to write this code um we're not really inventing anything new here of course once again we can prove that we're better than the machine um I personally prefer wrapping this in as state flow so that you can't do the downcast um but that's pretty much it uh interestingly enough unlike in my rehearsals uh the wonderful AI has decided to give you a little bit of a spoiler here because of course one of the main reasons why we enjoy using uh view models is also because they provide us a view model scope for doing um sus spending operations so in my case for example I could go into my repository I could save whatever my uh current mood as a string was so I could do that and then I could make sure that I actually grab my underscore change count and I update it by incrementing it by one okay cool of course our view model is not used yet so we will go back to our view model uh application here and we'll create one um our mood view model can just be created by uh using this Factory function this is a slightly different Factory function than what you might be used to from Android you might be using it usually to um or you would refer using the colon colon class there's a small limitation in cin native that doesn't allow us to Port that API but to be fair uh I don't think this is um a whole lot different now we can just wire up our change mood function um so in this case that would be just storing the element and we can grab ourselves out of the model the actual State and once again we can collect it as state not just generically but even with life cycle and that's pretty much all the changes we had to make here um I did create a little L function here uh for change mood just so that I don't have to change this in three different places um but of course it would have worked otherwise as well and now as we click things we can first of all also see that we're saving happy to the database and as I keep on clicking this I have a very hard time right now being here on clicking anything that's not happy to be quite honest with you um but yeah so this uh also works just as you would expect great so yeah um you the way that you work with view models uh generally is you can just have the uh view model Constructor function um that uses the curly braces rather than the round braces and class um and of course if you have a dependency injection framework that is actually aware of composed multi-platforms uh view models then you can also just use that one of course to retrieve your view model now of course we're standing here right and we've announced uh all of this stuff earlier today so how could there be a uh dependency injection framework that already has support for this well thanks to the absolute lightning speed adjacent work of the folks at coin um they actually already built uh an implementation of this uh against our uh previous RC's so if you use the latest beta version of coin you can already use it with composed view models to inject them which I think is pretty cool um if you see ano around uh during the conference make sure you thank him for this excellent work okay somehow that Applause even feels better because that one doesn't feel like it's for me so let's also still talk about navigation and in general once again what we're doing here is we are bringing jetpack navigation to Common code I once again want to stress that that just means that you have one more choice that you can make uh when you're picking a navigation Library the composed multiplatform Community has actually been very active ever since we've done um the first public releases um for building really cool Solutions um this is just one more solution the reason why we're bringing this is because these are very wellestablished and quite popular apis so if you're building an Android application that is using jaac navigation um this just makes it a whole lot easier to bring it to multiplatform okay so because all of this actually also ties in with view models and with life cycle this is kind of our little Capstone project here um so we're hopefully putting everything together um that we've seen so far in our navigation demo app okay so our task is pretty simple we have an individual start page over here we'll can take a brief look at what that will look like once we actually build it which is just a list of a whole bunch of fruits and then for each of these fruits um we have a specific subpage which first of all um has a little note section where we can just write a bunch of text and it also has a related fruit navigation section so that we can go to some other fruits before anyone says anything I looked it up avocado is technically a fruit and of course we want to have some sort of Stack based uh navigation here so let's actually go ahead and start uh constructing this here um we will start of course just in our entry point of our application need a little bit of extra space generally in uh the jetpack navigation Library uh most things start in the nav host and then we can just kind of start filling this in it requires a nav controller so we can create one of those um just using the remember nav controller function um so we can fit that one in here it typically requires a start route um and then it also requires um a Lambda in which we can provide some composable routes for example we already know that our start route is this specific start page we also want to make this slightly nicer um so what we can do is we can throw on a modifier um which first of all let's see here uh we probably need to make sure that we use the uh window insets padding uh in our case those would be again we try to remember here something like hello intellig good to have you I know you want attention um we can just do the save content here um and we can also just make sure that this actually fills the maximum size and just to make this a little bit more visual I did also prepare a couple of transitions um these just kind of like provide a nice little stack animation so that we can actually see what's going on rather than the default cross fade but that's not actually uh strictly necessary okay rather than just um printing out that we clicked on a fruit we actually want to grab our nav controller and we want to navigate to a different route for example the fruit form uh that we're working on with a specific fruit of course we should actually use the real fruit that we're use uh that we're getting back here we should probably also construct that route otherwise we not navigate anywhere so in this case we will actually use this placeholder syntax and we know that with our uh fruit page we have a couple of parameters we need to provide the current fruit that one we probably need to somehow extract from this route we actually can actually see that we have access to this backstack entry here using it but we can also give it a name can call it backstack entry um and we can see here okay we have uh the arguments and then in there um I think I can just call get string on fruit otherwise we'll say this is no fruit and I really hope that we won't hit this case during our little demo okay so now we know what the current fruit is it's just fruit when someone selects another fruit so when we have on select fruit we once again want to do something that looks pretty similar to what we've done up here um but let's make sure we actually navigate to the correct fruit that we wanted to have and then we also have an onback that's just the back button that we already previously saw um so in this case since this is all a stack based um navigation we can pop the back stack and I also have just a tiny bottom slot um that I can use uh to create some breadcrumbs those will just help us visualize um what it is that's actually happening okay so with that I believe uh most things should be in place for our application so let's take a peek and see what I forgot maybe I forgot something who knows we're all learning together that's the beautiful thing okay so we have our list of fruits here running on my iPhone scroll up and down I am technically a developer advocate so avocado that's close enough um you can see here that actually I um this is something we didn't quite discuss but each of these screens also has an Associated view model um that does a couple of operations in this case it just grows avocados um you can see that not just on the screen you can also see that over here in the terminal so you can see that these operations keep on running now as I click on the Apple uh you can see that the avocado view model is still on the back stack right so that keeps on running in the background but now we're also seeing all of those wonderful apples and of course as I continue here uh you can see down in our little breadcrumbs visualization very small um that we are indeed kind of creating this little backstack here so as I navigate back um we can actually see that each of the individual view models are cleared step by step so those operations stop until we arrive back at our main application which already looks pretty good but there is still a couple of issues here right so for example uh I'm an avocado seems like a note that I should be able to remember it's also important to remember uh that this keeps doctors away right um and at cin conf I'm going bananas but the problem is when I go back those are gone and now I don't remember whether I'm an avocado anymore of course this was just one of the classic problems um that you will encounter um if you use the remember function by default because remember when your composable leaves the composition um we'll also forget the state but with um the navigation Library also acting um as a place where you can put savea bles you can actually change this um to remember savable and if we run this uh same application once more we should hopefully uh make sure that uh all of our important notes are actually stored so once again Dr away life gives lemons cin con equals bananas if we go back still there look at that absolutely gorgeous and of course all the things that by default have some sort of remember savable inside their implementation for example this scrollable uh list if I go back here um you will also see that it does remember the scroll state so the avocado is still visible um as I navigate back even though um it's actually by default scrolled out a few great wonderful seems like we've built an amazing application here [Applause] great so yeah as you can see um there's a very natural Synergy between view models navigation and life cycle those all fit together quite well uh one of the topics we didn't talk about today just because of time limitations is also that we have support for things like dialogue destinations and of course we're continuing to integrate um this experimental Library um with things like deep linking so that someone can actually click on a link and get sent to a specific screen inside your composed multiplatform application IOS as well as common back handling you also saw me type a bunch of uh strings and routes and all these kind of things um when I was actually setting up my navigation um one of the very exciting things is that the composed navigation Library actually is getting type safety and of course that is not an Android only thing uh this is all being built on top of cutland X serialization which is a multi-platform serialization library so we're getting support for that uh in composed multiplatform in the near future as well so that hopefully you will make very few typos or if you do make them the compiler will yell at you so with that both building composed multiplatform applications and also taking existing uh jetpack compos applications on Android hopefully becomes a whole bunch easier um for you you with these new steps it's also really exciting because of course jetpack compose itself also keeps evolving right um we've seen today in the uh keynote that they're introducing the new strong skipping mode and you can already activate this as an experimental feature uh in composed multiplatform as well and really cut down on some unnecessary recompositions in your multiplatform applications we're also getting support for the shared element Transitions and lazy list animations that are coming with uh composed 1.7 um and you'll be able to build some really cool looking UI using that and of course the stabilization Journey continues um we continue to refine these things and of course we do that based on your feedback so here is my call to action for all of you please go ahead and try all this new stuff that we saw here with your applications because once again we evolve this using your feedback the easiest way to get started is to go to jb. compose and from there in less than three clicks you will end up on this page I will leave this as an exercise to the reader as to how you get there but we actually do have documentation for all the features we talked about so once again if you want to look up those life cycle diagrams that we saw here um as well as like all the modifiers the modifier order and precedent for common resources um and some more details for crossplatform routing you can do that on the multiplatform portal where you also see a whole bunch of other information yes because compose evolves with you it is really important um that if you do find something that doesn't behave the way you want to or where you're like wait a second that doesn't seem right that you do log a couple of issues for us you can do that in our issue tracker and of course we have a super helpful Community if you're looking into these things on the cotl Lang slack so make sure you stop on by there um and maybe say hello now again the wonderful thing about compos multiplatform is that I'm not really telling you a lot of new things all of this are established libraries so as you go through the rest of kenon and if you go to any of these talks there's a good chance that you can map them one to one to compose multiplatform as well some of these are case studies that uh happened earlier today so either you have a time machine or you can use the recording feature of course all these talks are recorded um of course we would love to uh send a couple of you folks also to an not talk um on coin um after all they've done some really exciting work here and this is of course the place where I'll also um plug the talk from my colleague um Elijah who's going to talk on what we do um to make sure that your composed multiplatform applications run really smoothly on iOS devices so here uh if you know this talk was very much like API surface and you saw what you can do um this one is really going to dive under the hood um and into the nitty-gritty details of what happens so if that's something you're interested in maybe take a look with that all I can say is I hope that you go ahead and enjoy compos multiplatform and of course don't forget vote using an application building compos multiplatform thank you very much [Music]
Info
Channel: Kotlin by JetBrains
Views: 5,794
Rating: undefined out of 5
Keywords: Kotlin, Kotlin Programming Language, Kotlin Multiplatform Mobile, Kotlin Android, Kotlin for server-side, Kotlin/JS, Programming language, Programming, Android development, Kotlin Multiplatform
Id: iIk755YpQlI
Channel Id: undefined
Length: 42min 43sec (2563 seconds)
Published: Wed Jun 19 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.