Android: Navigation uses the safe args plugin to pass parameters

1. Use configuration

Compared with the traditional way of passing parameters, afe args has the advantage of safe parameter types, and with the official support of Google, it is very convenient to pass parameters.

1. 根build.gradleAdd the plugin under the project

buildscript {
    ext.kotlin_version = "1.3.72"
    repositories {
        google()
        jcenter()
    }
    dependencies {
         classpath "com.android.tools.build:gradle:7.0.4"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
       classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

2, and then app的build.gradlereferenced in'androidx.navigation.safeargs.kotlin'

    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
    id 'androidx.navigation.safeargs.kotlin'
}

3. After adding the plug-in, return to nav_graph, switch to design mode, and add the parameters that need to be received to the target page

Here you need to pass parameters when FragmentA jumps to FragmentB, so set parameters for FragmentB, click FragmentB, click + on the right side of Arguments on the right panel, enter the key value of the parameter, specify the parameter type and default value, and you can quickly add parameters
insert image description here4. After adding, rebuildclick on the project, safeArgs will automatically generate some codes, /build/generated/source/navigation-argsyou can see in the directory that
insert image description heresafeArgs will generate corresponding classes according to the fragment tag in nav_graph,

  • The action tag will be “类名+Directions”named after,
  • The argument tag will be “类名+Args”named after .

After using safeArgs, pass parameters like this

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        tv.setOnClickListener {
            val navController = Navigation.findNavController(it)
            //通过safeArgs传递参数
            val navDestination = FragmentADirections.actionFragmentAToFragmentB2("test")
            navController.navigate(navDestination)
            
            // 普通方式传递参数
		   // val bundle = Bundle()
            // bundle.putString("key", "test")
            // navController.navigate(R.id.action_fragmentA_to_fragmentB2, bundle)
        }
    }

The receiving parameters are like this

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        arguments?.let {
            val value = FragmentBArgs.fromBundle(it).key
            .......
        }
        .......
    }

2. Examples

insert image description here

nav_main.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/nav_main"
    app:startDestination="@id/avalFragment">

    <fragment
        android:id="@+id/avalFragment"
        android:name="ir.MrMohamadHosein.navigationcomponent.AvalFragment"
        android:label="fragment_aval"
        tools:layout="@layout/fragment_aval" >

        <action
            android:id="@+id/action_avalFragment_to_dovomFragment"
            app:destination="@id/dovomFragment" />

    </fragment>

    <fragment
        android:id="@+id/dovomFragment"
        android:name="ir.MrMohamadHosein.navigationcomponent.DovomFragment"
        android:label="fragment_dovom"
        tools:layout="@layout/fragment_dovom" >
        <argument
            android:name="MyName"
            app:argType="string"
            android:defaultValue="no-name" />
    </fragment>

</navigation>

Note: Define the parameters you want to pass in the target Fragment, not define your pass parameters in the initial Fragment

1、MainActivity

class MainActivity : AppCompatActivity() {
    
    

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_main" />

</androidx.constraintlayout.widget.ConstraintLayout>

2、DownFragment, DovomFragment

2.1、DownstreamFragment

DownstreamFragment

class AvalFragment : Fragment() {
    
    
    lateinit var binding: FragmentAvalBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
        binding = FragmentAvalBinding.inflate(layoutInflater)
        return binding.root
    }

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

        binding.btnGoToSecondFragment.setOnClickListener {
    
    
            findNavController().navigate(
                AvalFragmentDirections.actionAvalFragmentToDovomFragment().setMyName("amir")
            )
        }

    }

}

fragment_aval.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AvalFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="fragment aval"
        android:textSize="36sp" />

    <Button
        android:id="@+id/btnGoToSecondFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="80dp"
        android:text="go to second fragment" />


</FrameLayout>

2.2、DovomFragment

DovomFragment

class DovomFragment : Fragment() {
    
    

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
        return inflater.inflate(R.layout.fragment_dovom, container, false)
    }

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

        val data = DovomFragmentArgs.fromBundle(requireArguments()).myName
        Toast.makeText(context, data, Toast.LENGTH_SHORT).show()

    }

}

fragment_dovom.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DovomFragment">

    <TextView
        android:textSize="36sp"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="fragment dovom" />

</FrameLayout>

reference

Guess you like

Origin blog.csdn.net/JMW1407/article/details/127991036