You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用androidx.navigation库时含斜杠地址导航崩溃问题

解决Android Navigation中含斜杠的自定义类型导航崩溃问题

问题场景

  • 自定义NavType<Address?>传递地址数据时,街道名称不含斜杠(如Green Street 1)的地址可正常完成导航
  • 街道名称含斜杠(如Green Street 1/3)的地址会触发「目标不存在」错误,直接导致应用崩溃
  • 根因是AndroidX Navigation底层基于URL的导航机制,斜杠是URL路径的分隔符,序列化后的JSON字符串中的斜杠会破坏导航路径的解析逻辑

解决方案

方案1:对序列化字符串做URL编码/解码

通过编码将斜杠转换为URL安全的格式,避免被Navigation误解析为路径分隔符,解码时再还原为原始字符串。修改后的AddressType实现如下:

import android.os.Bundle
import androidx.navigation.NavType
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import java.net.URLDecoder
import java.net.URLEncoder

@Serializable
data class Address(
    val city: String?,
    val companyId: Int,
    val country: String?,
    val gpsCoordinates: String?,
    val id: Int,
    val pointName: String? = null,
    val pointType: String,
    val postalCode: String?,
    val street: String?
)

val AddressType = object : NavType<Address?>(isNullableAllowed = true) {
    override fun get(bundle: Bundle, key: String): Address? {
        return bundle.getString(key)?.takeIf { it != "null" }
            ?.let { URLDecoder.decode(it, "UTF-8") }
            ?.let { Json.decodeFromString<Address>(it) }
    }

    override fun parseValue(value: String): Address? {
        return if (value == "null") {
            null
        } else {
            URLDecoder.decode(value, "UTF-8")
                .let { Json.decodeFromString<Address>(it) }
        }
    }

    override fun serializeAsValue(value: Address?): String {
        return Json.encodeToString(value)
            .let { URLEncoder.encode(it, "UTF-8") }
    }

    override fun put(bundle: Bundle, key: String, value: Address?) {
        bundle.putString(
            key,
            Json.encodeToString(value)
                .let { URLEncoder.encode(it, "UTF-8") }
        )
    }
}

方案2:使用Safe Args传递数据(推荐)

如果项目已集成Navigation Safe Args,可直接用它传递自定义序列化对象,完全避开URL解析的问题:

  1. 在模块的build.gradle中启用Safe Args插件:
plugins {
    id "androidx.navigation.safeargs.kotlin"
}
  1. 在NavGraph的目标页面中定义参数:
<argument
    android:name="address"
    app:argType="com.yourpackage.Address" />
  1. 通过生成的方向类完成导航和参数接收:
// 发起导航时传递地址
val action = HomeFragmentDirections.actionHomeToDetail(address)
findNavController().navigate(action)

// 目标页面接收地址
val args = DetailFragmentArgs.fromBundle(requireArguments())
val address = args.address

原理说明

  • Navigation在处理导航参数时,会将参数值拼接到类URL的路径结构中,斜杠会被识别为路径分隔符,导致参数被截断或解析失败
  • URL编码将特殊字符(如/)转换为%2F,确保Navigation不会误解析,解码后可还原为原始字符串
  • Safe Args底层通过Bundle传递序列化对象,完全绕开了URL解析逻辑,是更稳定可靠的实现方式

内容的提问来源于stack exchange,提问作者Cuyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:30:04