Jetpack Compose and the fall of Fragments
Introduction
This article is about how to structure your App using Jetpack Compose.
I won’t be talking about how to create your first composable function, they are already tons of articles on that subject.
Jetpack Compose, is brand new UIToolKit, based on functional and declarative principles that helps you create innovative and beautiful UI for Android (and some other platforms).
Fragments are dead, what’s replacing them?
In today’s Android world (yet Compose is still beta), we architecture our apps with the following hierarchy:
Application
- ActivityA
- Fragment1 + ViewModel1
- Fragment2 + ViewModel2 - ActivityB
- Fragment3 + ViewModel3
So now that we are removing Fragments from the equation, what is the equivalent and what do we do with the ViewModels?
Well let’s remember that MVVM stand for
- Model
- View
- ViewModel
And a fragment is nothing but a view (and that’s why you should refrain adding any business logic into them).
With Compose you can replace your Fragment by Composable function which act as your View.
Let’s illustrate that with the following App concept. It is a simple 2 screens app, you can go from screen 1 to screen 2 and from screen 2 to screen 1.
Each screen has a View and a ViewModel
In the activity we are going to instantiate the Views and the ViewModels
Application
- ActivityA
- ComposableScreen1View(ViewModel1)
- ComposableScreen2View(ViewModel2)
Just like we were providing the ViewModel to fragment (using the ktx or the ViewModel provider), we need to provide the ViewModel to the Composable function as a parameter. You will need to have your ViewModel instantiated in your activity, so you can provide it to the Composable function.
Activity.ktprivate val screen1ViewModel: Screen1ViewModel by viewModels()
ComposableFunctionScreen1View(screen1ViewModel)
NOTE: If you are using Koin, you get use the getViewModel() directly in the Composable function as a default parameter
fun ComposableFunctionScreen1View(viewModel: Screen1ViewModel = getViewModel())
Where do I put all these Composable functions?
That’s a fair question. You could be tempted to put everything into the Activity, in fact this is what most people do at the moment. Unfortunately this is not sustainable for big project.
Composable functions can be extracted and saved into a stand alone file. Which help a lot to structure the Android project.
My recommendation is to create a package for each feature/screen as follow:
screen1 represent your screen/feature, with its View and its ViewModel. The great thing here is that, there isn’t any XML file sitting far away, everything you need is in this package.
In the ui folder we can find:
- common hold the re-usable components, such as a custom MyButton for exemple
- navigation can store anything related to the navigation, the transitions for instance.
It actually make sense, isn’t it?
Your Composable functions can be used in your Activity and imported just like any Kotlin file. Same goes with re-usable components.
Conclusion
And that conclude this short article about Jetpack Compose file structure. I hope this has been useful. If you have any thoughts on how we can improve that further, please share your ideas in the comment section :)
GitHub project can be found here: https://github.com/sonique6784/ComposeArch