I have an Android app based on Jetpack Compose that uses the Google Play Services Barcode Scanner from the ML Kit to scan a QR Code.
On click of a FAB, the request to scan a new barcode is executed and the scanner window opens. When the scanning is finished (or cancelled or failed) a callback is invoked and I want to navigate the user to a new destination where the scanned code is used.
Passing the data to the new destination is the problem, however.
The data I need looks like this:
data class ScannerResult(
val state: ScannerState,
val displayValue: String?,
val rawValue: String?,
val exception: Exception? = null,
)
enum class ScannerState {
SUCCEEDED,
CANCELED,
FAILED
}
That way I can handle all three possible outcomes with one object.
I know that you should not pass any complex data (Parcelable, Serializable) via navigation, but I do not want to introduce a ViewModel just to save the data there and retrieve it afterwards.
Currently my destination looks like this:
fun NavGraphBuilder.newAccountScreen(onNavigateUp: () -> Unit) {
composable(
"$navRouteNewAccount/{state}/{rawValue}?exception={exception}", arguments = listOf(
navArgument("state") {
type = NavType.EnumType(ScannerState::class.java)
nullable = false
},
navArgument("rawValue") {
type = NavType.StringType
nullable = true
},
navArgument("exception") {
type = NavType.SerializableType(Exception::class.java)
nullable = true
}
)
) { backStackEntry ->
val result = backStackEntry.arguments?.let { bundle ->
ScannerResult(
bundle.serializable("state")!!,
bundle.getString("rawValue"),
bundle.serializable("exception")
)
}
if (result == null) {
Log.e("NewAccountScreen", "No result object found, navigating up")
onNavigateUp()
} else {
NewAccountScreen(
result = result,
onNavigateUp = onNavigateUp
)
}
}
}
In here I take the ScannerResult apart and reconstruct it on the other side. That however does not work because it throws the following exception: java.lang.UnsupportedOperationException: Serializables don't support default values.
I have also tried implementing Parcelable with ScannerResult, but I couldn't find a way to pass the parcelable directly to NavController.navigate().
Does anybody have an Idea as to how to solve this?