【问题标题】:safeargs argument not found in NavDirections在 NavDirections 中找不到 safeargs 参数
【发布时间】:2020-08-12 23:49:54
【问题描述】:

我已经实现了一个要在 nav_graph 中的片段之间传递的参数,但是当我尝试在原始片段中设置参数时,NavDirections 找不到该参数。

请注意,在尝试传递参数之前,导航可以正常工作。

如果我做一个干净的项目,我会丢失 NavDirections。如果我进行重建,我会失去论点。

Gradle:应用程序

    //Navigation
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
    apply plugin: "androidx.navigation.safeargs.kotlin"

nav_graph.xml

    <fragment
        android:id="@+id/destination_home"
        android:name="com.android.joncb.flightlogbook.HomeFragment"
        android:label="@string/lblHome"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/action_home_to_fltHistory"
            app:destination="@id/destination_fltHistory" />
        <action
            android:id="@+id/action_home_to_stats"
            app:destination="@id/destination_statistics" />
        <action
            android:id="@+id/action_home_to_newFlight"
            app:destination="@id/destination_newFlight" />
        <action
            android:id="@+id/action_home_to_fltDetails"
            app:destination="@id/destination_fltDetails" />
        <argument
            android:name="fltData"
            app:argType="string" />
    </fragment>

在我的主页片段中,我收到错误“未解析的引用:fltData”

        card_nextFlight.setOnClickListener {
            val actionDetails = HomeFragmentDirections.actionHomeToFltDetails()
            actionDetails.fltData ( flightData.toString())

            Navigation.findNavController(it).navigate(actionDetails)
        }

flightData 是一个数据类

data class FlightDTO(
    var airlineName: String, var faCode: String, var fltNo: String, var aircraft: String,
    var depAP: String, var arrAP: String, var schedDep: String, var schedArr: String,
    var date: String, var leg: Int = 0, var actDep: String = "", var actArr: String = "" ){

...

    override fun toString(): String {

        return "$airlineName $faCode $fltNo $aircraft $depAP $schedDep $arrAP $schedDep $date"
    }
}

我想通过将课程设为 Parcelable 来理想地通过该课程,但在我可以通过一个字符串之前,冒险沿着宗地线是没有意义的。

【问题讨论】:

    标签: android kotlin android-navigation android-safe-args


    【解决方案1】:

    你写错了你的 XML,这样想:我构建我的 XML 属性的方式是生成的代码看起来和在目的地之间接收的方式有点......

    所以基本上在您的 nav_graph.xml 中您应该更改为:

    <fragment
        android:id="@+id/destination_home"
        android:name="com.android.joncb.flightlogbook.HomeFragment"
        android:label="@string/lblHome"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/action_home_to_fltHistory"
            app:destination="@id/destination_fltHistory" />
        <action
            android:id="@+id/action_home_to_stats"
            app:destination="@id/destination_statistics" />
        <action
            android:id="@+id/action_home_to_newFlight"
            app:destination="@id/destination_newFlight" />
        <action
            android:id="@+id/action_home_to_fltDetails"
            app:destination="@id/destination_fltDetails">
            <argument
                android:name="fltData"
                app:argType="string" />
        </action>
    </fragment>
    

    在你的目的地,它应该看起来像:

    <fragment
        android:id="@+id/destination_fltDetails"
        android:name="com.android.joncb.flightlogbook.FlightDetailsFragment"
        android:label="@string/lblFlightDetails"
        tools:layout="@layout/fragment_flight_details">
        <argument
            android:name="fltData"
            app:argType="string" />
    </fragment>
    

    在您的航班详细信息片段中,使用以下方式接收属性:

    private val args: FlightDetailsFragmentArgs by navArgs()
    println(args.fltData) // prints the navigation data
    

    更新:

    忘记在 Home 片段中提及您的 OnClickListener,看起来更像这样:

    card_nextFlight.setOnClickListener {
        val actionDetails = HomeFragmentDirections.actionHomeToFltDetails(flightData.toString())
    
        Navigation.findNavController(it).navigate(actionDetails)
    }
    

    【讨论】:

    • 这是部分正确的。您不需要在操作旁边指定参数,只需要在目标声明中的参数(这里也称为destination_fltDetails)
    • @ror 好吧,如果您查看目的地的结构以及在这种情况下提供的数据是 flight_details。如果我理解你是正确的,那么这样做将使每个目的地都可以使用 flight_details ,这不会与例如一起使用。新航班目的地
    • @ror 或者你能澄清一下:)?
    • 感谢 ror 和 @Lucho。我已经让它工作了,你的两个 cmets 都有一个变化。请参阅下面的工作解决方案。
    • @Lucho 我想说的是:1.destination_home 节点不能有参数部分 2.destination_fltdetails 必须有参数部分但具有FlightDTO 的包限定名称 3.FlightDTO 类必须是可序列化的(实现接口可序列化)。支持你的答案。
    【解决方案2】:

    我没有传递数据类,而是创建了一个 JSON 字符串并传递了一个字符串

            card_nextFlight.setOnClickListener {
                val dataString = flightData.toJSONString()
                val actionDetails = HomeFragmentDirections.actionHomeToFltDetails(dataString)
    
                Navigation.findNavController(it).navigate(actionDetails)
            }
    

    要让它工作,我必须修改 actionHomeToFltDetails 函数以在 HomeFragmentsDirections 中接收字符串

        fun actionHomeToFltDetails(fltData: String): NavDirections = ActionHomeToFltDetails(fltData)
      }
    

    我无法让@Lucho 方法来处理目标片段中的 arg 以工作,因此恢复为包管理,并将 JSON 字符串转换回数据类

            const val ARG_PARAM1 = "fltData"
    .
    .
    .
            arguments?.let {
                argFltData = it.getString(ARG_PARAM1)
    
                Log.e("args","Passed Argument: $argFltData")
    
                fltData = gson.fromJson(argFltData, FlightDTO::class.java)
    
            }
    

    再次感谢您的意见,我希望这可以帮助其他人完成这出戏。

    【讨论】:

      【解决方案3】:

      我的错误如下。我有类似的东西

      NavDirections action =
              SpecifyAmountFragmentDirections
                  .actionSpecifyAmountFragmentToConfirmationFragment();
      

      我变成了类似的东西

      ConfirmationAction action =
              SpecifyAmountFragmentDirections
                  .actionSpecifyAmountFragmentToConfirmationFragment();
      

      【讨论】:

        【解决方案4】:

        就我而言,我写了一个这样的错误代码 -

        NavController navController = NavHostFragment.findNavController(this);
        NavDirections navDirections = MyDestinationFragmentDirections.actionMyAction(myArgumentValue);
        
        navController.navigate(navDirections.getActionId());
        

        那我把最后一行改成这个-

         navController.navigate(navDirections);
        

        最后,按预期工作!!!

        这背后的逻辑是,NavController 类中接受 int (resId of action) 的方法总是放空参数 -

        public void navigate(@IdRes int resId) {
                navigate(resId, null);
            }
        

        所以我们应该使用 -

         public void navigate(@NonNull NavDirections directions) {
                navigate(directions.getActionId(), directions.getArguments());
         }
        

        如果我们愿意通过动作传递参数的方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-02
          • 2023-03-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多