导航组件参数默认值

Navigation component arguments default value

在导航组件中,当从第一个片段向第二个片段发送参数时,默认值不是从导航图中获取的。

这是我的代码:

navigation_graph.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/firstFragment">


    <fragment
        android:id="@+id/firstFragment"
        android:name="com.example.navigationcomponent.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <action
            android:id="@+id/action_firstFragment_to_secondFragment"
            app:destination="@id/secondFragment"
            app:enterAnim="@anim/nav_default_enter_anim" />

        <argument
            android:name="clickFrom"
            app:argType="string"
            android:defaultValue="From First Fragment" />
        <argument
            android:name="clickFragmentPosition"
            app:argType="integer"
            android:defaultValue="1" />

    </fragment>

    <fragment
        android:id="@+id/secondFragment"
        android:name="com.example.navigationcomponent.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second" />


</navigation>

第一个片段:

class FirstFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val bundle = Bundle()
        bundle.putBoolean("IsFirstFragment", true)
        val navController = Navigation.findNavController(activity!!, R.id.my_nav_host_fragment)

        btnNext.setOnClickListener {
            navController.navigate(R.id.action_firstFragment_to_secondFragment, bundle)
        }
    }
}

第二个片段:

class SecondFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_second, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val isFromFirstFragment = arguments?.getBoolean("IsFirstFragment", false)
        Log.d(TAG, "$isFromFirstFragment")
        Log.d(TAG, "${FirstFragmentArgs.fromBundle(arguments!!).clickFrom} ${FirstFragmentArgs.fromBundle(arguments!!).clickFragmentPosition}")

        val navController = Navigation.findNavController(activity!!, R.id.my_nav_host_fragment)
        btnBack.setOnClickListener {
            navController.navigateUp()
        }

        navController.addOnDestinationChangedListener { controller, destination, arguments ->
            Log.d("TAG", "${destination.label}");
        }
    }

    companion object {
        private const val TAG: String = "SecondFragment"
    }
}

在第二个片段中获取默认值时出现空指针异常

Log.d(TAG, "${FirstFragmentArgs.fromBundle(arguments!!).clickFrom} ${FirstFragmentArgs.fromBundle(arguments!!).clickFragmentPosition}")

我的问题是,如何获取使用 navigation_graph.xml 设置的参数值?重新构建项目时,导航图已自动生成 getter。是否有任何架构可以使用默认值绑定自动生成的设置器?

如果您想将参数从 FirstFragment 发送到 SecondFragment,那么您应该将 navigation_graph.xml 替换为:

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/firstFragment">


    <fragment
        android:id="@+id/firstFragment"
        android:name="com.example.navigationcomponent.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <action
            android:id="@+id/action_firstFragment_to_secondFragment"
            app:destination="@id/secondFragment"
            app:enterAnim="@anim/nav_default_enter_anim" />

    </fragment>

    <fragment
        android:id="@+id/secondFragment"
        android:name="com.example.navigationcomponent.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second">

        <argument
            android:name="clickFrom"
            app:argType="string"
            android:defaultValue="From First Fragment" />

        <argument
            android:name="clickFragmentPosition"
            app:argType="integer"
            android:defaultValue="1" />

        <argument
            android:name="isFirstFragment"
            app:argType="boolean"
            android:defaultValue="false" />

    </fragment>


</navigation>

然后,您可以像这样从 FirstFragment 传递参数:

class FirstFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val navController = Navigation.findNavController(activity!!, R.id.my_nav_host_fragment)

        btnNext.setOnClickListener {
            navController.navigate(
                FirstFragmentDirections.actionFirstFragmentToSecondFragment( // this is an auto-generated class & method
                    // specify your arguments here: For example:
                    isFirstFragment = true,
                    clickFrom = "your argument here",
                    clickFragmentPosition = 1
                    // for default values, you can leave this blank
                )
            )
        }
    }
}

然后在 SecondFragment

中检索参数
class SecondFragment : Fragment() {

    private val arguments: SecondFragmentArgs by navArgs() // add this line to retrieve arguments from navigation

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_second, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val isFromFirstFragment = arguments.isFirstFragment
        Log.d(TAG, "$isFromFirstFragment")
        Log.d(TAG, "${arguments.clickFrom} ${arguments.clickFragmentPosition}")

        val navController = Navigation.findNavController(activity!!, R.id.my_nav_host_fragment)
        btnBack.setOnClickListener {
            navController.navigateUp()
        }

        navController.addOnDestinationChangedListener { controller, destination, arguments ->
            Log.d("TAG", "${destination.label}");
        }
    }

    companion object {
        private const val TAG: String = "SecondFragment"
    }
}

如果有人试图在 Java 中使用导航参数,这就是您在 SecondFragment

中检索参数的方式
boolean isFirstFragment = SecondFragmentArgs.fromBundle(getArguments()).getIsFirstFragment();