如何使用Navigation type safeargs插件将Parcelable类型的对象传递给Fragment

Jer*_*for 15 android android-fragments android-architecture-components android-jetpack

我正在重写我的简单UI应用程序以使用导航架构组件,我需要传递一个实现Parcelable的Pojo,没有看到任何关于如何做到这一点的文档.

任何帮助,将不胜感激.

Mar*_*ius 23

由于safe-args-gradle-plugin:1.0.0-alpha03您可以使用Parcelable完全限定的类名来使用对象:

app:argType="com.example.app.model.Item"
Run Code Online (Sandbox Code Playgroud)

现在支持Parcelable参数,使用app:type的完全限定类名.支持的唯一默认值是"@null"(https://issuetracker.google.com/issues/79563966)

资料来源:https://developer.android.com/jetpack/docs/release-notes

  • 如何与 Proguard 一起使用它?我崩溃了:`引起:java.lang.RuntimeException:java.lang.ClassNotFoundException:com.example.models.User` (2认同)
  • @PatrickSteiger您需要使用``-keep class className```规则保留此类。 (2认同)
  • 这似乎不适用于嵌套类。例如,`com.example.app.TestFragment.ViewModel` 将不起作用。有没有人找到解决方法? (2认同)
  • 我爱你@EpicPandaForce,有效!我将在此处添加一些关键字,以便人们可以更快地找到它:argtype Parcelable classnotfoundException dex (2认同)

Suy*_*van 8

我知道答案已经存在,但这可能会对某人有所帮助。 Code snippet

在build.gradle中添加此依赖项

ext{
     ...
     navigation_version = '1.0.0-alpha11'
}
dependencies {
     ...
     classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:$navigation_version"
}
Run Code Online (Sandbox Code Playgroud)

在app / build.gradle中

apply plugin: 'androidx.navigation.safeargs'
...
Run Code Online (Sandbox Code Playgroud)

在导航图中


 <fragment
            android:id="@+id/source_fragment_id"
            android:name="app.test.SourceFragment"
            android:label="@string/source_fragment_label"
            tools:layout="@layout/source_fragment_layout">

         <action
                android:id="@+id/action_source_fragment_to_destination_fragment"
                app:destination="@id/destination_fragment_id"
                ...
                />


</fragment>

<fragment
            android:id="@+id/destination_fragment_id"
            android:name="app.test.DestinationFragment"
            android:label="@string/destination_fragment_label"
            tools:layout="@layout/destination_fragment_layout">

        <argument
                android:name="variableName"
                app:argType="app.test.data.model.CustomModel" />

        ...

</fragment>
Run Code Online (Sandbox Code Playgroud)

注意:CustomModel应该是可打包的或可序列化的。

从SourceFragment导航到这个DestinationFragment时

val direction = SourceFragmentDirections.ActionSourceFragmentToDestinationFragment(customModel)
findNavController().navigate(direction)
Run Code Online (Sandbox Code Playgroud)

现在从DestinationFragment中的包中检索值

...
import app.test.DestinationFragmentArgs.fromBundle

class DestinationFragment : Fragment() {
   val variableName by lazy {
       fromBundle(arguments!!).variableName
   }

   ...
   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        Log.e(DESTINATION_FRAGMENT_TAG,"onCreateView")

        //Can use CustomModel variable here i.e. variableName


   }

}
Run Code Online (Sandbox Code Playgroud)


Lev*_*ira 7

现在你不能使用除整数,字符串,推断引用之外的类型的安全args,打开了一个问题,要求其他类型.

您现在可以做的是在使用navigate()方法导航到目标时通常传递一个:

var bundle = bundleOf("amount" to amount)
view.findNavController().navigate(R.id.confirmationAction, bundle)
Run Code Online (Sandbox Code Playgroud)

你可以使用通常的getArguments(或kotlin中的参数)来检索:

val tv = view.findViewById(R.id.textViewAmount)
tv.text = arguments.getString("amount")
Run Code Online (Sandbox Code Playgroud)


sbo*_*000 6

您可以使用boolean, reference, integer, long, string,enum甚至parcelableserializable但忘记最后一个;-)

最好使用最新的插件版本safe-args-gradle-plugin:1.0.0-alpha08并指定完全限定的类名:

<fragment
    ...>
    <argument
        android:name="data"
        app:argType="com.example.ParcelableData" />
</fragment>
Run Code Online (Sandbox Code Playgroud)

从你的

package com.example

data class ParcelableData(val content: String) : Parcelable { ... }
Run Code Online (Sandbox Code Playgroud)

您可以发送所有argTypes 的数组:

<argument
        android:name="data"
        app:argType="string[]" />
Run Code Online (Sandbox Code Playgroud)