Kotlin Multiplatform Jetpack Compose
- Kotlin Multiplatform Jetpack Compose is a declarative framework for sharing user interfaces across multiple platforms.
- It is based on Kotlin Multiplatform and Jetpack Compose, and is available for:
- Android
- Desktop
- iOS (in beta)
- Web (in alpha)
KMP Jetpack Compose - Why?
- Accelerated UI development: Build your UI once, use it on all platforms.
- Android UI and architecture skills can be applied to other platforms by sharing UI using Compose APIs.
- Rich ecosystem: Leverage Kotlin libraries and frameworks.
- Easy integration with every platform: Full access to native APIs and platform-specific user interfaces.
- Component-level reuse: Create customizable widgets for all platforms.
- Gradual adoption: Share individual screens or entire user interfaces between platforms.
Challenges
- ViewModels: Not available on iOS or Desktop.
- Image loading: Coil, Glide, and Picasso are Android-only.
- Firebase: Integration across multiple platforms?
- Navigation: Jetpack Navigation is Android-only.
KMP Jetpack Compose – ViewModel 1
Alternatives to familiar Android tools:
- lifecycle-viewmodel-compose: Use ViewModels in the shared module (experimental).
- Moko MVVM: Multiplatform MVVM architecture components.
Using Moko MVVM
Add dependencies in commonMain:
commonMainApi("dev.icerock.moko:mvvm-core:0.16.1")
commonMainApi("dev.icerock.moko:mvvm-compose:0.16.1")
commonMainApi("dev.icerock.moko:mvvm-flow:0.16.1")
commonMainApi("dev.icerock.moko:mvvm-flow-compose:0.16.1")
Factory method for viewModels:
@Composable
fun <T : ViewModel> getViewModel(
key: Any,
factory: ViewModelFactory<T>
): T {
return getViewModel(
key = key,
klass = factory.kClass,
viewModelBlock = factory::createViewModel
)
}
ViewModel Usage
homepageViewModel: HomepageViewModel = getViewModel(
key = "homepage_view_model",
factory = viewModelFactory {
KoinHelper().getHomePageViewModel()
}
)
getHomePageViewModel can be a common method or an expect function with platform-specific actual implementations.
fun getHomePageViewModel() : HomepageViewModel
actual fun getHomePageViewModel() : HomepageViewModel{
return HomepageViewModel(get(), get())
}
actual fun getHomePageViewModel():HomepageViewModel{
return get<HomepageViewModel>()
}
Image Loading: Coil & Kamel
Coil v3 supports multiplatform; Kamel is built specifically for Compose Multiplatform.
implementation("media.kamel:kamel-image:1.0.0")
Kamel Usage
KamelImage(
resource = asyncPainterResource(data = url),
contentDescription = contentDescription,
contentScale= contentScale,
modifier= modifier.fillMaxSize(),
onFailure = {
LoggerVisibility.Error.log("NetworkImage", "Error on loading image: $url")
}
)
The resource parameter can be a URL, string, or file.
Firebase in KMP
GitLive is a project that provides Firebase support for KMP.
api("dev.gitlive:firebase-config:1.13.0")
After setup, use Firebase just as you would in Android:
val firebaseRemoteConfig = Firebase.remoteConfig
firebaseRemoteConfig.fetchAndActivate()
Navigation
implementation("org.jetbrains.androidx.navigation:navigation-compose:2.7.0-alpha07")
Configure NavHost as you would in Android Compose:
NavHost(
navController = LocalNavController.current.navController,
startDestination = NavigationRoute.HomePageScreen.uniqueName,
modifier = Modifier.fillMaxSize()
){
composable(route = NavigationRoute.HomePageScreen.uniqueName) {
HomepageScreen()
}
composable(
route = NavigationRoute.CharactersDetailScreen.uniqueName + NavigationRoute.CharactersDetailScreen.pathParam,
arguments = listOf(navArgument("id"){type = NavType.IntType}),
deepLinks = listOf(NavDeepLink(NavigationRoute.CharactersDetailScreen.deeplinkBase +
NavigationRoute.CharactersDetailScreen.uniqueName + NavigationRoute.CharactersDetailScreen.pathParam))
){
it.arguments?.getInt("id")?.run {
CharacterDetailScreen(this)
}
}
}
Pros & Cons
Pros
- One Team
- One codebase
- Multiple apps with shared code
- Ability to write native code anytime
Cons
- Jetpack Compose is still in beta or alpha for some platforms
- Many APIs are experimental and not yet production-ready