Build a Full MVVM Application for iOS and Android with Compose Multiplatform in Kotlin

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I'm going to teach you how to build a basic to-do application for both Android and iOS using a compos multiplatform this application will utilize a local database and for that matter we will use a realm database which is a mobile solution provided by mongodb it's designed to seamlessly integrate with mobile apps for both platforms and above all it's easy to use stay [Music] tuned all right so the first step is to download a blank project template from a camp wizard like we always do we are targeting Android and iOS with a shared UI this project template however doesn't come with a UI theme package like a regular Android composed template which means we need to generate a material three colors on our own also this template uses material to compose Library by default but we're going to change that easily by appending number three to this dependency and syncing the project once again now the project will use the newest material 3 design Library awesome next to get those material three colors you can go to the material theme Builder web application customize and Download Material three colors for your project but since this will be a rather simple project I'm going to specify only two colors that I'm going to use here and not all of them and anyhow open up the app coton file which is the root composable for both platforms here I'm creating only two custom colors and passing them to light and dark color schemas we are using primary and primary container colors in this demo project which is okay finally create the new colors variable that will inherit either dark or light colors depending on whether a user has enabled a dark theme from the system settings this variable is then passed directly to our root material theme function awesome we are done with theming the next step is to handle the navigation in our application and for that purpose we're going to use a voyager navigation library for which I have already made a separate video anyhow be sure to specify those four artifacts for this Library so the first one is used for the navigation the second one for transition animations the third one for a view model and the last one for integration with a coin dependency injection Library you also need to include the coin core artifact for that matter perfect we need to create two screens for this application right so the first one a home screen where we are going to list all active and completed tasks and the second one a task screen which we're going to use to create a new tasks in our application each screen needs to implement a simple screen interface and override a Content composable where we Define the content of each screen for now I will leave those empty and get back to it a little bit later before that we need to go to the app cing file and Def find the Navigator along with a start destination of our application we are also defining a transition between those screens to be a slight transition awesome afterwards we need to create a model class to represent a task in our application since we're going to use a mongodb realm as a local database we need to implement a realm object to represent this model class as a collection but before that be sure to add a dependency for a mongodb realm as well as a cing core routines besides that we also need a realm plugin and include it in a Bo Grail build files finally sync the project and you're good to go when declaring a properties with a realm object we need to place them inside the body of the class using a VAR keyword I will add a couple of information and add an object ID that will automatically generate a unique identifier for each task document in this collection perfect while we are in here let's also create one more rapper class that will be used to handle the data or the state of our data in our application I have already made a complete separate video explaining this class in more details but basically it allows us to indicate the state of our data and update our UI accordingly there is one more helper composable function that also animates the content of our screen when transitioning between different states now it's time to design how our home screen will look like as always we can add a scaffold along with a top a bar on the top then we could also use a floating action button so that we can navigate to the task screen later on the center of the screen we are going to have a column and the two sections inside it the first one will be used for active tasks and the second one for a completed tasks instead of creating a separate UI for each one of them I will create the single compos function that will be reused in a two places so below that create a new function called display tasks it should take multiple parameters like a tasks wrapped inside the request State wrapper then a Boolean value to indicate whether the show active or a completed tasks and a couple of lambdas that we're going to use to interact with a database here inside we are remembering two properties show dialog will decide whether to show an alert dialogue to prompt the user to confirm a task deletion and the second one that will hold the reference of a task that needs to be deleted below that add an if check to show this alert dialogue only if this value is true and trigger on delete Lambda if a user clicks yes button so if a user closes this dialogue in any way we are just resetting both of those properties to their default values great so before we continue with this composable I'm going to create two more components the first one will be used to display a loading indicator to indicate a loading state of our data and the second one to indicate an error or an empty state of our data after that we're going to create one more custom composable function that will be used inside the lazy column of both active and a completed test so here we are adding a couple of lambdas that should be hoisted up in the composable hierarchy then we are passing a task along with a Boolean indicator that we're going to use to decide which UI to show and what logic to trigger this view when displayed as an active task will display a star icon that we're going to use to trigger and update the favorite property of the task itself and when this displayed as a completed task this view will show a strike through task title with a slightly less visibility and a delete icon instead of the star icon because only completed tasks will show an option to delete all right so now we can go back to the home screen and continue where we have started so below an alert dialogue Place one column then a title text that will indicate whether this is an active or a completed section of the screen and a lazy column below that as well now since the tasks property is wed within the request State I'm going to make use of that helper function to decide what kind of a UI I want to display based on the current state of our data so when this data is loading we are displaying a loading screen if we receive some error then the error screen and only if we successfully fetch the data only then we are showing a lazy column also we could do one more check here to show an empty text if there are no any tasks inside this list so afterwards inside the lazy column just add a task view to properly show a task information now we can go back and call this display tasks composable from the home screen in two places for each section of our screen and each one of those sections will take an equal amount of space on this screen all right so we are one step closer before we start with a task screen we are going to create a mongodb class that will hold all the functionality to interact with a local database here I will initialize a realm object and set its default value to be null then we're going to create here a function to initialize and open up the realm so that we can inter with the database this is also the place where you pass all your collection model classes and in this case I have only one this function will be called as soon as this class is initialized down below let's create a function to read all tasks from the database so to read those tasks that are not marked as completed and we are also going to sort those same tasks by their favorite value which means tasks that are marked as a favorite will be shown first in the result below that add one more function this time to read the completed tasks instead and finally for now just one more function which we're going to use to insert a new task document inside the database collection perfect the next thing we need to create the view model for the home screen and encapsulate the logic from the mongodb we are going to use a screen model which is the part of the Voyager screen model artifact so just create here a new class and implement the screen model interface then I will declare two variables with a corresponding backing properties and their default value will be request State idle we're going to update them as soon as this view model is initialized and I will add here a slight delay so that we can see the loading screen before the data is fetched after that we're going to read the data and update the variables great now you can see that this view model class requires a mongodb class instance so to properly inject that into our view model I'm going to use a coin dependency injection Library let's go back to the app file and create the module variable then initialize the mongodb as a singl tone and below that I'm going to create here and actually inject The View model and the pass that provided among B instance as well for the view models we're going to use a factory block and here just pass a get function because the coin is smart enough to decide what kind of a dependency we need to provide here finally create a function to initialize a coin Library along with this module and call the function inside the app function which will initialize that on both Android and iOS we could also call this function inside the on create method of the main activity and inside the IOS app separately but for the Simplicity I will leave that here for now so we have handled the view model and the last thing is to initialize it so in the home screen just call get screen model function and pass a home view model as a type that's all we can create here two additional variables to hold each one of those two types of tasks we can pass them Below in the corresponding functions and we are ready to observe the data from the UI awesome uh next let's switch over to a test screen so I'm going to make it a data class instead and add one more additional parameter that we are going to use to decide whether to trigger update or insert operation with our database collection so if we pass an actual task object here then it will mean that we are updating a selected task otherwise we are creating a new one let's add here a scaffold then a top a bar as well and as a title I will add a text field where we're going to modify the title property of the task also a back arrow so that we can navigate back to our home screen to hold the title value for the text field I will create a new property but also a property for a description as well after that I will add a floating action button that should trigger the logic to either insert or update a selected task this button will be visible only if both of those values are not empty of course based on the task parameter of the task screen we are going to either trigger an update or a insert operation with a database but we will handle that a bit later we just need one more element on the screen and that is a text field for a description property of our task so just add it down below great before we continue let's also handle a navigation between those two screens so first from the home screen when The Floating Action button is clicked we want to navigate to a task screen and not pass anything that way a task argument will be null which will indicate that we want to create a new task also when we select one of those tasks from a Act tasks list we want to navigate to a Tas screen but also pass a selected task after that in the task screen when the back arrow is clicked we also want to navigate back and also when The Floating Action button is clicked we want to go back no matter if a task is null or not amazing now before we handle a task screen I want to create one more model class that we're going to use to handle the appropriate logic when it comes to to interacting with a database I will create a seal class with all possible interactions that we're going to need that way we are not going to expose any function from The View model and instead a user will pass those actions to the view model itself which will then communicate with a mongodb before we continue with a task vew model let's go back to the mongodb class and the call configure function inside the init blog so that we can trigger the configuration as soon as the class is initialized perfect while we are here let's also add a couple of more functions to handle different operations update task function is the first one here specify a task as a parameter and then below we are querying the collection to search and update the task that we are looking for by providing its ID then we are searching for the latest version of that object and updating its properties next let's add a function to update only its completed property so here we are also doing the same thing only updating the single property completed next let's add another function to update its favorite property this time like before just pass a new Boolean value to the parameters as well as a task object so that we can get its ID then query and update its value so here we could also just specify a task ID as a parameter along with this Boolean value but nevertheless I'm just going to pass this whole object this time we only need one more function to delete a selected task just pass here a task as a parameter then query and search for the task with a specified ID and call a delete function great those are all the functionalities that we are going to need this example could be improved further more like we could add some kind of a return type to those functions to indicate if we receive an error for example but for the demo purposes I'm just loging here an error message by using a print Ln let it be your homework improve this example to return a proper response by using a request to State class that we have already made great so the next thing we need to create a new view model this time for the test screen we are also going to inject a mongodb class and add two functions for adding and updating the task those functions will be private here since we are not going to expose them to the UI instead I will create one more function that will be used to receive an action from our user and then from here trigger both of those functions for updating and adding a new task to the collection so open up the app cotlin file to specify how to provide the instance of the view model with a coin Library so that we don't forget to do that later after that inside the task screen initialize the view model and then inside the onclick L of The Floating Action button trigger an appropriate action within the view model awesome I think that we can now try and launch this application to see whether we should be able to add and update the task let's do it I will first test this on a Android emulator okay so apparently we have one UI issue we can see only the first section for active tasks but not the second one for the completed tasks so let's go back to the project and as you can see here both of those sections have a weight modifier set to 1 F which means they should take an equal amount of space open up the function definition and you will see that here we have actually forgot to pass the modifier parameter to the column down below so let's do that and let's launch the application once again and now we can see both of those sections great so open up the task screen by clicking that button and this way we are basically passing a null as a task screen parameter which means we want to create the new task so fill in some dumb information and click the button to create a new task we are going to receive here an exception because inside the lazy column for the key parameter we need to specify only primitive values in this case we have passed the whole object ID so we need to convert that into the hex string value instead and Now launch the application once again and there we go so now we can see that actual task that we have already made so let's update this task and click the button so you can see that the task has not been updated the reason why is because we have forgot to add an ID of the task argument that we have passed to the test screen so let's go back and specify a task ID when triggering an update action great so launch the application once again and let's try updating that task one more time perfect it works we will handle the logic for updating completed and favorite properties a bit later for now we need to fix one more issue as you can see in the task screen if we try to focus the text field then the software keyboard will overlap with our Floating Action button to avoid that just open up the Android manifest file and specify this attribute to have a value of adjust resize then everything should work fine fine perfect before we go back to the project let's open up the project inside the X code so that we can test that out on a iOS simulator as well when opening the project with X code be sure that you select the IOS app directory or otherwise you may get an error so launch the application and there you go everything here looks and works the same way as with a Android emulator so the last thing that is left to do is Implement those additional functionalities inside the home view model let's add a function for updating a completed property a function for updating a favorite property and one more to delete a selected task we will be able to delete the task only after the task is marked as a completed we need to add one more function to handle UI actions from here great let's go back to the home screen and below that in those two sections we need to handle lambdas for on favorite on complete and the oncomplete and on delete in the completed Test Section everything looks good for now so launch the application to test it out when we click the check boox on the active task it immediately transfers to a completed task section because we have changed its completed property we can also create a new task here just to show and see how those tasks will be rearranged in the list when they favorite property is updated so those items that has favorite properties equal to True will be listed first and if you click delete icon down below then you will need to confirm an item deletion before deleting it completely let's launch also the app on iOS simulator and here as you can see see everything works great as well so that would be all for this video tutorial now you have seen how to successfully Implement a data persistence layer for both Android and iOS using compose multiplatform to share the UI between a different platforms what do you think about that are you a fan of a mongodb realm database comment down below and let me know other than that be sure to like this video but only if you find it helpful for [Applause] watching
Info
Channel: Stevdza-San
Views: 24,750
Rating: undefined out of 5
Keywords: kotlin, multiplatform, compose, jetpack compose, android, ios, compose-multiplatform, kmp, xcode, android studio, to-do, basic app, mvvm, architecture, clean, how to, guide, tutorial
Id: 1TLk36FdmMA
Channel Id: undefined
Length: 23min 36sec (1416 seconds)
Published: Fri Mar 22 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.