使用 Jetpack 传输数据

Transmit data with Jetpack

寻找一种更优雅的方式来使用 Jetpack 传输数据

现在我传递的数据如下:

override fun onListItemClick(itemIndex: Int, itemCode: String) {
        val bundle = Bundle()
        bundle.putString(KEY_TARGET_GUID, (adapter.getItem(itemIndex) as Target).guid)
        findNavController().navigate(R.id.target_edit, bundle)
    }

然后像这样在另一个片段中获取它:

private val targetGuid: String
        get() = arguments?.getString(KEY_TARGET_GUID, "") ?: ""

我看到 google 的人在 codelab 中这样做了,但在他的示例中,他们创建了 class FlowStepFragmentArgs,而且内容很多

data class FlowStepFragmentArgs(val flowStepNumber: Int = 2) : NavArgs {
    fun toBundle(): Bundle {
        val result = Bundle()
        result.putInt("flowStepNumber", this.flowStepNumber)
        return result
    }

    companion object {
        @JvmStatic
        fun fromBundle(bundle: Bundle): FlowStepFragmentArgs {
            bundle.setClassLoader(FlowStepFragmentArgs::class.java.classLoader)
            val __flowStepNumber : Int
            if (bundle.containsKey("flowStepNumber")) {
                __flowStepNumber = bundle.getInt("flowStepNumber")
            } else {
                __flowStepNumber = 2
            }
            return FlowStepFragmentArgs(__flowStepNumber)
        }
    }
}

:我的情况下如何漂亮的传输数据

据我所知,使用 Jetpack Navigation 传递数据实际上只有 2 个选项。

1) 使用捆绑包。在这里我发现 budnleOf(x to y) 函数非常方便

    val targetGuid = adapter.getItem(itemIndex) as Target).guid)
    val bundle = bundleOf(KEY_TARGET_GUID, targetGuid)
    findNavController().navigate(R.id.target_edit, bundle)

2) 通过在导航图中定义目的地参数。这将生成代码。假设你 R.id.target_edit 是一个片段:

<fragment
    android:id="@+id/target_edit"
    android:name="com.example.TargetEditFragment"
    tools:layout="@layout/fragment_target_edit">
    <argument
        android:name="targetGuid"
        android:defaultValue="@null"
        app:argType="com.example.Target"
        app:nullable="true"/>
 </fragment>

然后在你的 TargetEditFragment

override fun onCreate(savedInstanceState: Bundle?) {
  val targetGuid =
    arguments?.let { TargetEditFragmentArgs.fromBundle(it).targetGuid }
}

使用导航架构,您可以这样做:- 让您在 navigation.xml 文件中声明片段为:-

 <fragment
    android:id="@+id/fragment_a"
    android:name="com.example.FragmentA">
    <action android:id="@+id/action_item_click"
        app:destination="@id/fragment_b" />
</fragment>

<fragment
    android:id="@+id/fragment_b"
    android:name="com.example.fragmentB">
    <argument android:name="id" app:argType="string" android:defaultValue="sample data" />
</fragment>

注:-

  1. 为动作发起的每个目的地创建一个 class。 这个 class 的名称是发起的名称 目的地,附加单词“Directions”。
  2. 此 class 具有针对在原始目标中定义的每个操作的方法。

因此对于 FragmentA class 它将生成为 FragmentADirections 例如。 -

override fun onListItemClick(itemIndex: Int, itemCode: String) {
    findNavController().navigate(FragmentADirections.actionItemClick("Pass YOUR_STRING"))
}

注:-

  1. 为接收目的地创建了一个class。这个 class 的名称是目的地的名称,附加了单词“Args”。

并且对于 FragmentB class 它将生成,因为您可以获得数据作为 FragmentBArgs 例如:-

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // do what you want with this id
    arguments?.let {bundle->
       val id = FragmentBArgs.fromBundle(bundle).id
    }
              // OR you can do also as
    // val id = arguments?.getString("id").orEmpty()
}

详情请参考https://developer.android.com/guide/navigation/navigation-pass-data