Compose Navigation: Passing Objects

it is very easy to pass primitive and simple Args in navigation , but what if your compose function accept an argument of specific type for example your User Model?
the answer is by sending your object as JSON String then convert this JSON back to your TYPE in NavHost function :)
you can do conversion by using a library called Moshi
Moshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and Kotlin classes
the key functions you deal with: toJson and fromJson
toJson : to convert object to JSON String
fromJson: to convert JSON to object.
add library to your app module build.gradle:
implementation("com.squareup.moshi:moshi:1.14.0")
implementation("com.squareup.moshi:moshi-kotlin:1.14.0") //for KotlinAdaperFactory
make an object of type Moshi:
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory()) //form moshi-kotlin
.build()
create an Adapter from your class :
val jsonAdapter = moshi.adapter(User::class.java).lenient() // am using user class
now convert object to JSON :
val userJson = jsonAdapter.toJson(user)
and pass it instead of String args :
user/details/{user}
// we want to pass it instead of {user}
"user/details/{${userJson}}"
// of course you will use this when you do
// naVController.navigate("user/details/{${userJson}}")
inside NavHost:
NavHost{
composable(
"user/details/{user}"
) {backStackEntry ->
val userJsonString = backStackEntry.arguments?.getString("user")
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory()) //form moshi-kotlin
.build()
val jsonAdapter = moshi.adapter(User::class.java).lenient()
val userObject = jsonAdapter.fromJson(userJsonString)
UserDetailScreen(userObject)
}
and lastly your composable :
@Composable
fun UserDetailScreen(userObject)
){...}
just to recap you have to do this in NavHost:
composable(
route = Destination.ServiceDetails.routeName+"/{service}" ,
){
val serviceJsonString = it.arguments?.getString("service")
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory()) //form moahi-kotlin
.build()
val jsonAdapter = moshi.adapter(ServiceModel::class.java).lenient()
val serviceObject = serviceJsonString?.let { it1 -> jsonAdapter.fromJson(it1) }
ShowService(serviceObject!!)
}
and from the point when you need to navigate:
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory()) //form moahi-kotlin
.build()
.build()
val jsonAdapter = moshi.adapter(ServiceModel::class.java).lenient()
val serviceToJson =jsonAdapter.toJson(mainViewModel.viewState.value.selectedServiceModel)
navController.navigate(Destination.ServiceDetails.routeName+"/${serviceToJson}")
thanks for reading:)
References :