NavController.OnDestinationChangedListener 传递的 destination.id 与触发的导航操作 ID 不匹配

gar*_*707 15 android android-jetpack-navigation

在我的 Android 项目中,我有一个非常简单的导航图,包括两个片段:Master 和 Detail:

<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/wordsListFragment">

    <fragment
        android:id="@+id/wordsListFragment"
        android:name="com.***.presentation.view.WordsListFragment"
        android:label="List"
        tools:layout="@layout/words_list_fragment">
        <action
            android:id="@+id/action_wordsListFragment_to_wordDetailsFragment"
            app:destination="@id/wordDetailsFragment" />
    </fragment>
    <fragment
        android:id="@+id/wordDetailsFragment"
        android:name="com.***.presentation.view.WordDetailsFragment"
        android:label="Details"
        tools:layout="@layout/word_details_fragment" />
</navigation>
Run Code Online (Sandbox Code Playgroud)

导航本身在两个方向上都可以正常工作,包括“返回”行为。在那个项目中,我有一个活动,我在其中实施OnDestinationChangedListener. 所有这些都根据谷歌的以下文档:NavController 更新 UI

当用户单击列表项时(在主片段上),我调用以下方法:

findNavController().navigate(R.id.action_wordsListFragment_to_wordDetailsFragment, null)
Run Code Online (Sandbox Code Playgroud)

然后在父活动中,我有以下实现:

private fun setupNavController() {
    navigationController = findNavController(R.id.nav_mainhost_fragment_container)
    navigationController.addOnDestinationChangedListener(mainDestinationChangedListener)
    appBarConfiguration = AppBarConfiguration(navigationController.graph)
    setupActionBarWithNavController(navigationController, appBarConfiguration)
}
Run Code Online (Sandbox Code Playgroud)

那就是侦听器对象:

private val mainDestinationChangedListener = 
NavController.OnDestinationChangedListener { controller, destination, arguments ->        

if (destination.id == R.id.action_wordsListFragment_to_wordDetailsFragment) {
        actionBar?.hide()
    } else {
        actionBar?.show()
    }
}
Run Code Online (Sandbox Code Playgroud)

destination.id不匹配R.id.action_wordsListFragment_to_wordDetailsFragment

我已经尝试清理项目,清理IDE缓存,gradle缓存,但生成的标识符仍然不匹配。我还尝试通过 Safe Args 使用导航:

val action = WordsListFragmentDirections.actionWordsListFragmentToWordDetailsFragment()
findNavController().navigate(action)
Run Code Online (Sandbox Code Playgroud)

但给定侦听器中的结果始终相同(即不匹配)。

调试中的一些值:

findNavController().navigate(1000021) //R.id.action_wordsListFragment_to_wordDetailsFragment
Run Code Online (Sandbox Code Playgroud)

但堆栈上的下一个调用有另一个值: 在此处输入图片说明 什么也匹配destination.id传递给的值OnDestinationChangedListener

destination.id //2131231018
Run Code Online (Sandbox Code Playgroud)

非常欢迎您提供任何提示。我只想识别目标或操作 ID 并相应地调整工具栏。

Moh*_*laa 7

您正在将fragmentIdactionId进行比较,因此它始终为 false

这里 if (destination.id == R.id.action_wordsListFragment_to_wordDetailsFragment)

由于destination.idfragmentId 并且 R.id.action_wordsListFragment_to_wordDetailsFragmentactionId

为了使其工作,您应该比较两个片段 ID,例如

if (destination.id == R.id.wordDetailsFragment)
Run Code Online (Sandbox Code Playgroud)

*编辑

首先你应该找到你的 navControler ,然后听它的目的地变化。

val navController = findNavController(this,R.id.nav_host_fragment)// this maybe change
navController.addOnDestinationChangedListener { controller, destination, arguments ->
   if(destination.id == R.id.wordDetailsFragment) {
       actionBar?.hide()
   } else {
       actionBar?.show()
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的努力,但您仍然没有明白我上面描述的问题。我的监听器调用:“mainDestinationChangedListener”已添加,正在工作并在必要时触发。通知侦听器的机制有效,但“destination.id”与导航操作 ID 或目的地(详细信息)片段不匹配。 (3认同)
  • 恐怕你是不对的。我已经检查过这种情况,但事实并非如此。*destination.id* 是 2131231021,而 *R.id.wordDetailsFragment* 是:1000241 这不是我第一次进行 Android 开发。我只是不明白什么(以及如何)改变了 *destination.id* (2认同)

小智 6

问题出在 Android studio 调试器上。如果我在 logcat 中打印该值或将其分配给变量,则该值为 2XXXXXXXXX,但如果我使用调试器进行评估,则该值为 1XXXXXX。

我已经检查了 APK 中的操作 id(R.id.xxxx) 十六进制代码。当我将十六进制代码转换为整数时,它给出 2XXXXXXXXX 中的值,该值等于 logcat 中打印的值