At the just-concluded Google IO conference, Google unveiled the Android Jetpack architecture component; As stated on the website, Android Jetpack is a set of components, tools, and guidance to help you build great Android applications. The Android Jetpack component connects the existing support library with architectural components and divides them into four categories: Architecture, Foundation, Behavior, and UI. It allows developers to create better, high-quality apps.

Navigation Architecture Component introduction

The Navigation editor is part of the Android Jetpack and AndroidX dependencies library and aims to simplify Navigation in Android development. Navigation helps us deal with the complexity of FragmentTransaction interactions between activities and fragments. Navigation can also handle transitions of pages well. And of course those of you who are familiar with IOS development are going to look at this and think this is StoryBoard. Google’s official introduction of Navigation is not very detailed (English is too poor ~~~), so let’s implement it!!

Navigation using

Create an Android Jetpack application (Android Studio 3.2 Canary 13 and later)

Add the dependent
  1. The project’s build. Gradle:
buildscript {
	...
	repositories {
    		google()
	}
	dependencies {
    		...
    		classpath 'android. Arch. Navigation: navigation - safe - the args - gradle - plugin: 1.0.0 - alpha01'}}Copy the code
  1. Add the following dependencies to your app’s build.gradle:
apply plugin: 'androidx.navigation.safeargs'
Copy the code
implementation 'android. Arch. Navigation: navigation - fragments: 1.0.0 - alpha01'
implementation 'android. Arch. Navigation: navigation - UI: 1.0.0 - alpha01'
Copy the code
Create the navigation editor

Right-click the RES resource folder: New -> Android Resource File -> Enter the name of the XML file and select Navigation -> OK for resource type

<? xml version="1.0" encoding="utf-8"? > <navigation xmlns:android="http://schemas.android.com/apk/res/android">

</navigation>
Copy the code
Add a navigation view to the Activity

Since Navigation needs to bind the Fragment view to the activity, let’s change it:

<? xml version="1.0" encoding="utf-8"? > <android.support.constraint.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:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <fragment
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1"
        app:navGraph="@navigation/main_navigation" />

</android.support.constraint.ConstraintLayout>
Copy the code

The fragment in the activity is NavHostFragment by default. NavHostFragment is associated with the navigation editor by navGraph. App :defaultNavHost=”true” allows NavHostFragment to handle system return events

Edit Navigation Navigation view
<? 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"
    app:startDestination="@+id/main_fragment">


    <fragment
        android:name="com.wangjun.app.jetpacktodolist.ui.main.MainFragment"
        android:id= "@+id/main_fragment"
        android:label="@string/main_fragment_title"
        tools:layout="@layout/main_fragment">


    </fragment>


    <activity
        android:id="@+id/settings_activity"
        android:name="com.wangjun.app.jetpacktodolist.ui.SettingActivity"
        android:label="@string/activity_settings"
        tools:layout="@layout/setting_activity"
        />

</navigation>

Copy the code

We see that the navigation TAB declares an app:startDestination=”@+ ID /main_fragment” attribute, which is the default view loaded by the navigator

Navigation jump — Action

Now we can see that our navigation editor has two views, main_fragment and settings_activity. If we need to jump from the main_fragment to settings_activity, You can add the action tag to the main_fragment to complete the jump

<? 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"
    app:startDestination="@+id/main_fragment">


    <fragment
        android:name="com.wangjun.app.jetpacktodolist.ui.main.MainFragment"
        android:id= "@+id/main_fragment"
        android:label="@string/main_fragment_title"
        tools:layout="@layout/main_fragment"> <! Jump to SettingActivity--> < Action Android :id="@+id/action_main_fragment_to_settings_activity"
            app:destination="@id/settings_activity" />

    </fragment>


    <activity
        android:id="@+id/settings_activity"
        android:name="com.wangjun.app.jetpacktodolist.ui.SettingActivity"
        android:label="@string/activity_settings"
        tools:layout="@layout/setting_activity"
        />

</navigation>
Copy the code

App: Destination in the Action tag is the view from which we load the navigation

Of course we can also do this by dragging in the navigation editor

Next we add a button to the MainFragment to complete the jump SettingActivity

<? xml version="1.0" encoding="utf-8"? > <android.support.constraint.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainFragment">

    <android.support.v7.widget.AppCompatButton
        android:id="@+id/btn_setting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.5" />

</android.support.constraint.ConstraintLayout>

Copy the code
class MainFragment : Fragment() { companion object { fun newInstance() = MainFragment() } private lateinit var viewModel: MainViewModel override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState: Bundle?) : View { val view = inflater.inflate(R.layout.main_fragment, container,false)

        view.findViewById<AppCompatButton>(R.id.btn_setting).setOnClickListener {
            Navigation.findNavController(view).navigate(R.id.action_main_fragment_to_settings_activity)
        }


        return view
    }
}
Copy the code

We see through the Navigation. FindNavController (view) get a NavController, through NavController. Navigate (R.i d.x XXX) corresponding to the current view of a particular Action, So we can jump. Isn’t it easy ~~~

Adding a transition animation is also very simple, we just need to add the following properties to the action

<fragment
        android:name="com.wangjun.app.jetpacktodolist.ui.main.MainFragment"
        android:id= "@+id/main_fragment"
        android:label="@string/main_fragment_title"
        tools:layout="@layout/main_fragment">

        <action
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            android:id="@+id/action_main_fragment_to_settings_activity"
            app:destination="@id/settings_activity" />

</fragment>
    
Copy the code

To transfer data

As before, we can pass data through bundles

Handwriting in code

 <fragment
        android:id="@+id/main2_fragment"
        android:name="com.wangjun.app.jetpacktodolist.ui.main.Main2Fragment"
        android:label="@string/main2_fragment_title"
        tools:layout="@layout/main2_fragment">

        <argument android:name="testArg"
            app:type="string"
            android:defaultValue="Hello Leon"
            />

        <argument
            android:name="testArg2"
            android:defaultValue="Your Majesty asked me to patrol the mountains."
            app:type="string" />

</fragment>

Copy the code

Navigation editor added

MainFragment Indicates that parameters are transmitted to the Main2Fragment

class MainFragment : Fragment() { companion object { fun newInstance() = MainFragment() } private lateinit var viewModel: MainViewModel override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState: Bundle?) : View { val view = inflater.inflate(R.layout.main_fragment, container,false) view.findViewById<AppCompatButton>(R.id.btn_setting).setOnClickListener { Navigation. FindNavController (view). Navigate (da ction_main_fragment_to_settings_activity R.i)} / jump * / * * * parameters view.findViewById<AppCompatButton>(R.id.btn_main2).setOnClickListener { val bundle = bundleOf("testArg" to "Nice to meet you."."testArg2" to "Are you a joke from the monkey?")
            Navigation.findNavController(view).navigate(
                    R.id.action_main_fragment_to_main2_fragment,
                    bundle)
        }

        return view
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

    }

}
Copy the code
class Main2Fragment : Fragment() {

    private lateinit var testArg: String
    private lateinit var testArg2: String

    companion object {
        fun newInstance() = Main2Fragment()
    }

    @SuppressLint("SetTextI18n") override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState: Bundle?) : View { val view = inflater.inflate(R.layout.main2_fragment, container,false) arguments? .let {testArg = it["testArg"] as String
            testArg2 = it["testArg2"] as String
        }

        var tvMain = view.findViewById<AppCompatTextView>(R.id.tv_main)

        tvMain.text = "$testArg---$testArg2"

        return view
    }

}
Copy the code

We found that the parameter is passed through NavController, the source code is as follows:

NavController.java

 /**
     * Navigate to a destination from the current navigation graph. This supports both navigating
     * via an {@link NavDestination#getAction(int) action} and directly navigating to a destination.
     *
     * @param resId an {@link NavDestination#getAction(int) action} id or a destination id to
     *              navigate to
     * @param args arguments to pass to the destination
     */
    public final void navigate(@IdRes int resId, @Nullable Bundle args) {
        navigate(resId, args, null);
    }
    
Copy the code

Deep link deep-link

In fact, it is very easy to understand, that is, we used to say that the custom URL using Scheme to jump parameters

navigation.xml

<navigation>
    <activity
        android:id="@+id/settings_activity"
        android:name="com.wangjun.app.jetpacktodolist.ui.SettingActivity"
        android:label="@string/activity_settings"
        tools:layout="@layout/setting_activity"> <! <deepLink app:uri="www.leonwang.com/hello/{testArg}" />

    </activity>

</navigation>
Copy the code

AndroidManifest.xml

<activity
            android:name=".ui.SettingActivity"
            android:label="@string/activity_settings">

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="https"/>
                <data android:scheme="http"/>
                <data android:host="www.leonwang.com"/>
                <data android:pathPrefix="/hello/"/>
            </intent-filter>

</activity>

Copy the code
Pay attention to

In order to ensure proper use of navigation, we need to override onSupportNavigateUp in the target Activity to ensure that the navigator rolls back the stack correctly, according to the official documentation.

override fun onSupportNavigateUp(): Boolean {
	return navController.navigateUp()
}
Copy the code

The last

Okay, so much for the basic use of navigation components, DEMO. For more details, please refer to the official documentation