Status Update
Comments
jb...@google.com <jb...@google.com>
il...@google.com <il...@google.com> #2
Branch: androidx-master-dev
commit b90079595f33f58fece04026a97faa0d243acdb1
Author: Yuichi Araki <yaraki@google.com>
Date: Wed Sep 18 16:55:49 2019
Change the way to detect mismatch between POJO and query
This fixes cursor mismatch warnings with expandProjection.
Bug: 140759491
Test: QueryMethodProcessorTest
Change-Id: I7659002e5e0d1ef60fc1af2a625c0c36da0664d8
M room/compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
M room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
M room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
M room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt
ed...@gmail.com <ed...@gmail.com> #3
il...@google.com <il...@google.com> #4
Branch: androidx-master-dev
commit bdde5a1a970ddc9007b28de4aa29d60ffa588f08
Author: Yigit Boyar <yboyar@google.com>
Date: Thu Apr 16 16:47:05 2020
Re-factor how errors are dismissed when query is re-written
This CL changes how we handle errors/warnings if query is
re-written.
There was a bug in expandProjection where we would report warnings
for things that Room already fixes automatically (
The solution to that problem (I7659002e5e0d1ef60fc1af2a625c0c36da0664d8)
solved it by deferring validating of columns until after re-write
decision is made. Unfortunately, this required changing PojoRowAdapter
to have a dummy mapping until it is validating, make it hard to use
as it does have a non-null mapping which is not useful.
This CL partially reverts that change and instead rely on the log
deferring logic we have in Context. This way, we don't need to break
the stability of PojoRowAdapter while still having the ability to
drop warnings that room fixes. This will also play nicer when we
have different query re-writing options that can use more information
about the query results.
Bug: 153387066
Bug: 140759491
Test: existing tests pass
Change-Id: I2ec967c763d33d7a3ff02c1a13c6953b460d1e5f
M room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
M room/compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
M room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
cl...@google.com <cl...@google.com>
ap...@google.com <ap...@google.com> #5
Branch: androidx-main
commit 757c9fb13fa75779086fa3ac2f440d2f5dd5bc96
Author: Clara Fok <clarafok@google.com>
Date: Tue May 07 11:49:14 2024
Fix SavedStateHandle.toRoute
SavedStateHandle arguments are taken directly from a bundle, which is formatted by NavType#put. When we decode the arguments, we need to read it with NavType#get.
Test: ./gradlew navigation:navigation-common:cC
Test: ./gradlew navigation:navigation-compose:cC
Bug: 339026523
Relnote: "SavedStateHandle.toRoute() now takes in a typeMap parameter for custom argument types"
Change-Id: Ie39fb2afad346928a34bc309513fa17f16cefa8c
M navigation/navigation-common/api/2.8.0-beta01.txt
M navigation/navigation-common/api/current.txt
M navigation/navigation-common/api/restricted_2.8.0-beta01.txt
M navigation/navigation-common/api/restricted_current.txt
M navigation/navigation-common/src/androidTest/java/androidx/navigation/serialization/RouteDecoderTest.kt
M navigation/navigation-common/src/main/java/androidx/navigation/SavedStateHandle.kt
M navigation/navigation-common/src/main/java/androidx/navigation/serialization/RouteDecoder.kt
M navigation/navigation-common/src/main/java/androidx/navigation/serialization/RouteDeserializer.kt
M navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostControllerTest.kt
cl...@google.com <cl...@google.com> #6
Fixed internally and will be available in navigation 2.8.0-beta01
ed...@gmail.com <ed...@gmail.com> #7
pr...@google.com <pr...@google.com> #8
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-common:2.8.0-beta01
androidx.navigation:navigation-compose:2.8.0-beta01
je...@gmail.com <je...@gmail.com> #9
This seems to be still be busted (same error) if you change isNullableAllowed = true (I don't have any errors when changing the same code to isNullableAllowed = false AND <IndividualId>)
Example:
Custom Class
@JvmInline
@Serializable
value class IndividualId(val value: String)
NavType for nullable:
val IndividualIdNullableNavType = object : NavType<IndividualId?>(
isNullableAllowed = true
) {
override fun get(bundle: Bundle, key: String): IndividualId? = bundle.getString(key)?.let { IndividualId(it) }
override fun put(bundle: Bundle, key: String, value: IndividualId?) {
value?.let { bundle.putString(key, it.value) }
}
override fun parseValue(value: String): IndividualId? {
if (value == "null") return null
return Json.decodeFromString<IndividualId>(value)
}
override fun serializeAsValue(value: IndividualId?): String = value?.let { Json.encodeToString(IndividualId.serializer(), it) } ?: ""
}
NavHost code:
composable<IndividualEditRoute>(mapOf(
typeOf<IndividualId?>() to IndividualIdNullableNavType,
)) { backStackEntry ->
Log.w("TEST", "Before") // prints
val individualEditRoute = backStackEntry.toRoute<IndividualEditRoute>()
Log.w("TEST", "After: individualEditRoute == $individualEditRoute") // never gets here because: ClassCastException: IndividualId cannot be cast to java.lang.String
IndividualEditScreen(navController)
}
The following works (no error):
onClick = {
navController.navigate(IndividualEditRoute())
},
The following will cause a "ClassCastException: IndividualId cannot be cast to java.lang.String"
onClick = {
navController.navigate(IndividualEditRoute(IndividualId("123")))
},
cl...@google.com <cl...@google.com> #11
Re
ga...@gmail.com <ga...@gmail.com> #12
I'm also having this issue. I have created a repo for showcasing this:
In there you will find another case with a Parcelable object. In my case is quite strange since the logcat shows this error:
Process: com.bobbyesp.navigationbugreport, PID: 23169
kotlinx.serialization.SerializationException: Serializer for class 'Companion' is not found.
Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:278)
at kotlinx.serialization.SerializersKt.serializer(Unknown Source:1)
at androidx.navigation.NavGraph.setStartDestination(NavGraph.kt:404)
cl...@google.com <cl...@google.com> #13
Re
But based on your source code, it is your startDestination in song
arg for your SongInformationPage
.
With safe args, you can conveniently pass in starting arguments by passing in a class instance. The arguments will automatically be available within the starting composable.
This means your nested graph should be
navigation<UtilitiesNavigator>(
startDestination = SongInformationPage(song = ...),
)
If your startDestination does not contain arguments, then you can pass in either:
@Serializable
object MyDestination
startDestination = MyDestination
--- OR ---
@Serializable
class MyDestination
startDestination = MyDestination::class
If you have further questions, please file a separate bug so it is easier for other users with the same question to locate the answer.
ga...@gmail.com <ga...@gmail.com> #14
du...@matechmobile.com <du...@matechmobile.com> #15
here is my code for you guys to look around:
fun setNavController(mNavController: NavController) {
this.navController = mNavController
navController.graph = navController.createGraph(startDestination = nav_routes.manual_add_otp_data) {
fragment<AddOtpManualFragment, AddOtpData>(
typeMap = mapOf(typeOf<AddOtpData>() to getCustomParametersType<AddOtpData>())
) {
label = nav_routes.manual_add_otp_data
}
}
}
--------
private inline fun <reified T : Parcelable> getCustomParametersType(nullable: Boolean = false) =
object : NavType<T>(
isNullableAllowed = nullable
) {
override fun put(bundle: Bundle, key: String, value: T) {
// Handle null case if the type is nullable
bundle.putParcelable(key, value)
}
override fun get(bundle: Bundle, key: String): T? {
// Return null if the value is nullable and not present
return if (isNullableAllowed) {
bundle.getParcelable(key)
} else {
bundle.getParcelable(key)
?: throw IllegalArgumentException("No value present for non-nullable type")
}
}
override fun parseValue(value: String): T {
// Decode and deserialize the string into the object
return Json.decodeFromString(value)
}
override fun serializeAsValue(value: T): String {
// Encode the object into a JSON string and Uri encode it
return Uri.encode(Json.encodeToString(value))
}
}
---------
@Serializable
@Parcelize
data class AddOtpData(val otpAuthDB: OtpAuthDB) : Parcelable
that all, thanks
Description
Version used: 2.8.0-alpha08
Devices/Android versions reproduced on: Pixel 6a (Android 14)
Getting the custom arg in a ViewModel when using just serializables instead of parcelables with this NavType:
val bookType = object : NavType<Book>(isNullableAllowed = false) {
override fun get(bundle: Bundle, key: String): Book? {
return bundle.getString(key)?.let { Json.decodeFromString<Book>(it) }
}
override fun parseValue(value: String) = Json.decodeFromString<Book>(value)
override fun serializeAsValue(value: Book): String = Json.encodeToString(value)
override fun put(bundle: Bundle, key: String, value: Book) {
bundle.putString(key, Json.encodeToString(value))
}
}
It works well if I get the value from the NavBackStackEntry but if I do this in the ViewModel:
val bookDetail = savedStateHandle.toRoute<BookDetail>()
I get this error when navigating to the detail:
java.lang.ClassCastException: java.lang.String cannot be cast to com.example.composenavigation.typesafety.Book
You can see an example in:
The navigation is in the file: TypeSafetyNavigation.kt
Thanks in advance!