首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Deeplink空字符串参数

Deeplink空字符串参数
EN

Stack Overflow用户
提问于 2022-01-31 11:30:55
回答 2查看 386关注 0票数 4

我正在应用程序中使用捷联导航作为导航解决方案。

当使用生成的安全args而不是深度链接策略时,我面临着不一致的行为。

假设我有以下导航图:

代码语言:javascript
复制
<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的方法

  • 使用id action_home_dest_to_deeplink_dest的导航操作
  • 深链example://my-deelink-frag?myArg={myarg}

DeepLinkFragment中,我使用navArgs()函数来反序列化传入的Bundle,并显示一个简单的Toast消息。

代码语言:javascript
复制
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()
    }
}

在使用生成的安全args导航时,我可以发送一个空字符串作为myArg的值。没问题。

代码语言:javascript
复制
findNavController().navigate(HomeFragmentDirections.actionHomeDestToDeeplinkDest(""))

但是,当使用空字符串作为参数通过深度链接方式导航时:

代码语言:javascript
复制
val arg = ""
findNavController().navigate("example://my-deelink-frag?myArg=${arg}".toUri())

我跟踪到了堆栈轨迹:

代码语言:javascript
复制
 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代码。

代码语言:javascript
复制
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)
    }
  }
}

查看代码,似乎是一个空字符串使bundle.getString("myarg")返回null而不是空字符串?!

作为一个修正,我可以添加android:defaultValue

然而,我不认为是正确的解决办法。

代码语言:javascript
复制
<argument
    android:name="myarg"
    android:defaultValue=""
    app:argType="string" />

在使用deeplinks时,这是已知的限制吗?

EN

回答 2

Stack Overflow用户

发布于 2022-02-13 18:38:14

不确定这是否完全回答了你的问题,但你所做的一切看起来都是正确的。下面根据我自己的经验,做一些相关的说明。

内部LINKS

我可能会使用SafeArgs进行应用程序内部的导航,或者像在我的这段代码中那样调用findNavController.navigate。就我个人而言,我不太喜欢更多的Android标记。

外部LINKS

如果你希望链接从电子邮件等来源工作,那么深度链接选项是最合适的,但你也需要验证输入。正如您似乎所指出的,一个空的默认值本身可能是不够的。

因此,在使用DeepLinkFragmentArgs之前,我将确保您获得了所需的控件。例如,在过去,我有时会发现,在允许导航进行之前进行验证是有用的--例如在货代活动中首先接收深度链接。这意味着我可以阻止深度链接执行,而Chrome是最顶端的(因为这会导致诸如重新创建主活动之类的问题)。

移动深孔

顺便说一句,我发现gmail等电子邮件客户端可能不允许定制URI方案深度链接,因此我的示例使用Android https应用程序,以防您感兴趣。

票数 0
EN

Stack Overflow用户

发布于 2022-02-13 19:12:10

可能不能将空字符串作为参数传递;对于string,通常会将"@null"作为默认值传递(这也需要一个可空字段);但如果您不想使用任何空值,则最好是字符串"default"。如果某些内容可能看起来不一致,您可能没有在AndroidManifest.xml中引用默认的导航图XML,这仅仅定义了深度链接的入口点。此外,可能需要版本2.5.0-alpha01,以便使用当前的AGP 7.1.1进行构建。没有对错,但是让NavController来处理它是很方便的--与编写代码相比,生成代码是首选的。

至少在普通的HTTP中,%02%03将是一个空的查询-字符串参数(但尚未测试)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70925235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档