Skip to main content

Jetpack Compose Navigationでオブジェクトを渡して画面遷移する

Jetpack Composeで画面遷移時にオブジェクトを渡して遷移したい
intentやargumentで今までできたのでやろうとしたらNavigationだとできないみたい
そんなわけでやり方


・dataの渡し方
複雑なパラメーターは渡せないので一回jsonにする
まじかって思うけど、まじらしい
https://stackoverflow.com/questions/65610003/pass-parcelable-argument-with-compose-navigation
呼ぶ側

val json = Uri.encode(Gson().toJson(a))
navController.navigate("hogehoge/$json")

受け取る側

composable(route = "hogehoge/fugafuga",
    arguments = listOf(
        navArgument("fugafuga") {
            type = AType()
        }
    )
) { backStackEntry ->
    val a = backStackEntry.arguments?.getParcel("fugafuga", A::class.java)
        ?: return@composable
class AType : NavType<A>(isNullableAllowed = false) {
    override fun get(bundle: Bundle, key: String): A? {
        return bundle.getParcel(key, A::class.java)
    }

    override fun parseValue(value: String): A {
        return Gson().fromJson(value, A::class.java)
    }

    override fun put(bundle: Bundle, key: String, value: A) {
        bundle.putParcelable(key, value)
    }
}

 

・Parcelable
CREATORを作る必要があるが、別で定義してると自動補完が効かない
なので以下のように実装する
https://stackoverflow.com/questions/58725845/kotlin-multiple-named-companion-objects

companion object {
    private const val a = "a"

    @JvmField
    val CREATOR = object: Parcelable.Creator<A> {
        override fun createFromParcel(parcel: Parcel): A {
            return A(parcel)
        }

        override fun newArray(size: Int): Array<A?> {
            return arrayOfNulls(size)
        }
    }
}

 

・getParcelableExtraはdeprecated
https://stackoverflow.com/questions/73019160/the-getparcelableextra-method-is-deprecated

fun <T: Parcelable> Bundle.getParcel(key: String, clazz: Class<T>): T? {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        this.getParcelable(key, clazz)
    } else {
        @Suppress("DEPRECATION") this.getParcelable(key)
    }
}

関連記事:

Pocket