我正在使用 Jetpack Navigation作为我的应用程序中的导航解决方案。
我在使用 generated safe args 时遇到了不一致的行为与深度链接策略相反。
假设我有以下导航图:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@+id/home_dest">
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
android:label="@string/home"
tools:layout="@layout/home_fragment" >
<action
android:id="@+id/action_home_dest_to_deeplink_dest"
app:destination="@id/deeplink_dest" />
</fragment>
<fragment
android:id="@+id/deeplink_dest"
android:name="com.example.android.codelabs.navigation.DeepLinkFragment"
android:label="@string/deeplink"
tools:layout="@layout/deeplink_fragment">
<argument
android:name="myarg"
app:argType="string" />
<deepLink app:uri="example://my-deelink-frag?myArg={myarg}" />
</fragment>
</navigation>
我已经定义了两种导航到 DeepLinkFragment
的方法。 :action_home_dest_to_deeplink_dest
的导航操作example://my-deelink-frag?myArg={myarg}
在
DeepLinkFragment
我正在使用 navArgs()
反序列化传入 Bundle
的函数并显示一个简单的 Toast
信息。class DeepLinkFragment : Fragment() {
private val args : DeepLinkFragmentArgs by navArgs()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Toast.makeText(requireContext(), args.myarg, Toast.LENGTH_SHORT).show()
}
}
使用 generated safe args 导航时我可以发送一个空字符串作为 myArg
的值.没问题。
findNavController().navigate(HomeFragmentDirections.actionHomeDestToDeeplinkDest(""))
但是,当通过深度链接方式使用空字符串作为参数进行导航时:val arg = ""
findNavController().navigate("example://my-deelink-frag?myArg=${arg}".toUri())
我得到以下堆栈跟踪: Caused by: java.lang.IllegalArgumentException: Required argument "myarg" is missing and does not have an android:defaultValue
at com.example.android.codelabs.navigation.DeepLinkFragmentArgs$Companion.fromBundle(DeepLinkFragmentArgs.kt:29)
at com.example.android.codelabs.navigation.DeepLinkFragmentArgs.fromBundle(Unknown Source:2)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:52)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:34)
at com.example.android.codelabs.navigation.DeepLinkFragment.getArgs(DeepLinkFragment.kt:30)
at com.example.android.codelabs.navigation.DeepLinkFragment.onViewCreated(DeepLinkFragment.kt:34)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:233)
at android.app.ActivityThread.main(ActivityThread.java:8068)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
来自生成的 DeeplinkFragmentArgs
代码public data class DeepLinkFragmentArgs(
public val myarg: String = ""
) : NavArgs {
public fun toBundle(): Bundle {
val result = Bundle()
result.putString("myarg", this.myarg)
return result
}
public companion object {
@JvmStatic
public fun fromBundle(bundle: Bundle): DeepLinkFragmentArgs {
bundle.setClassLoader(DeepLinkFragmentArgs::class.java.classLoader)
val __myarg : String?
if (bundle.containsKey("myarg")) {
__myarg = bundle.getString("myarg")
if (__myarg == null) {
throw IllegalArgumentException("Argument \"myarg\" is marked as non-null but was passed a null value.")
}
} else {
__myarg = ""
}
return DeepLinkFragmentArgs(__myarg)
}
}
}
Looking at the code it seems as if an empty string is making the
bundle.getString("myarg")
returnnull
instead of the empty string?!
作为修复,我可以添加
android:defaultValue
.但是我认为这不是正确的解决方案。
<argument
android:name="myarg"
android:defaultValue=""
app:argType="string" />
这是使用深度链接时的已知限制吗?
最佳答案
不确定这是否完全回答了您的问题,但您所做的一切看起来都是正确的。以下是根据我自己的经验的一些相关说明。
内部链接
我可能会使用 SafeArgs 在应用程序内部进行导航,或者直接调用 findNavController.navigate
如 this code of mine .就我个人而言,我不太喜欢更多的 Android XML 标记。
外部链接
如果您希望链接来自电子邮件等来源,那么深度链接选项是最合适的,但您还需要验证输入。正如您似乎指出的那样,一个空的默认值本身可能是不够的。
因此,在使用 DeepLinkFragmentArgs 之前,我会确保您获得所需的控制。例如,在过去,我有时发现在允许导航继续之前进行验证很有用 - 例如,首先在 Forwarder Activity 中接收深层链接。 .这意味着我可以阻止在 Chrome 自定义选项卡位于最顶层时执行深层链接(因为这会导致诸如重新创建主要 Activity 之类的问题)。
移动深度链接
顺便说一句,我发现 gmail 等电子邮件客户端可能不允许自定义 URI 方案深层链接,所以我的示例使用 Android https applinks ,以防万一您对此感兴趣。
关于android - 深层链接空字符串参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70925235/