What is Android Routing?

It mainly maps the page forward relationship and distributes the page request to the specified page according to the routing table.

Ii. Android Routing scenarios

  1. The App receives a notification. Click the notification to open a page in the App
  2. Click a link in the browser App to open a page of the App
  3. Operation activity needs to dynamically replace native pages with H5 pages
  4. To open a page, you need some conditions. You need to verify the conditions before you open that page
  5. Unauthorized App pages will be blocked
  6. H5 open links in all platforms are the same, convenient unified jump
  7. Open an APP, if the APP exists, open it directly, if not, go to the download page to download

Three,Why do you need a routing framework?

The Android native system already gives us The AndroidManifest to manage page jumps, such as startActivity, so why use a routing framework? Let’s briefly analyze the significance of the routing framework:

  1. Showing Intent: When a project is large, the class dependency coupling is too large for componentized splitting
  2. Implicit Intents: Cooperative development is difficult. Do you know what parameters to call
  3. Every Activity registered with Scheme can be opened directly, which is a security risk
  4. The centralized management of AndroidMainfest is bloated
  5. The route cannot be dynamically modified. If the page fails, the route cannot be dynamically degraded
  6. The jump cannot be intercepted dynamically. For example, when the user is not logged in, the login page is opened. After the login succeeds, the user opens the page that he wanted to open
  7. H5, Android, and iOS addresses are different, which is not conducive to unified jump
  8. In some complex business scenarios (such as e-commerce), flexibility is relatively strong, and many functions are dynamically configured by operation personnel. For example, when delivering an active page, we do not know the specific target page in advance, but if we make an agreement in advance and do page mapping in advance, we can configure freely.
  9. Simplifying the code, a few lines of jump code down to a single line of code, this should be easy for everyone to understand, is nothing more than encapsulating a block of code.

Four, choose what kind of routing framework is better?

In the end, routing is designed to solve all kinds of weird needs that developers encounter. When choosing a routing framework, it should be simple to use, less intrusive, and easy to maintain. It should not affect your original code, and write as little code as possible.

ARouter is a middleware that provides routing function for pages and services in Alibaba’s open source Android platform. It is a framework for helping Android App to carry out componentization transformation, supporting routing, communication and decoupling between modules, and advocating simplicity and sufficient use.

GitHub: github.com/alibaba/ARo…

Advantages of ARouter:

  1. Support to directly parse the standard URL to jump, and automatically inject parameters to the target page
  2. Support multi-module project use
  3. You can add multiple interceptors and customize the interception order
  4. Support for dependency injection and can be used as a separate dependency injection framework
  5. Support InstantRun
  6. Support for MultiDex(Google solution)
  7. Mapping relationships are classified by group, managed at different levels, and initialized on demand
  8. You can specify global and local demotion policies
  9. Pages, interceptors, services, and other components are automatically registered with the framework
  10. Supports multiple ways to configure transitions
  11. Obtaining Fragments
  12. Full support for Kotlin and blending (see Other #5 at the end of this article for configuration)
  13. Support third-party App hardening (automatic registration using arouter-register)
  14. Support for generating routing documents
  15. Provides IDE plug-ins with easy association paths and target classes
  16. Support for incremental compilation (no incremental compilation after document generation is enabled)

Typical applications of ARouter:

  1. Mapping from external URLS to internal pages, as well as parameter passing and parsing
  2. Cross – module page jump, module decoupling
  3. Intercept the jump process, processing logics such as landing and burial point
  4. Cross-module API calls do component decoupling by controlling reverse

ARouter = ARouter = ARouter

Step 1: ARouter configuration (add dependencies, introduce libraries)

Open the build.gradle file and import ARouter’s remote library in the dependencies {} configuration.

android {
    defaultConfig {
       
         // Omit the preceding code...
        
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}

dependencies {
    implementation 'com. Alibaba: arouter - API: 1.5.1'
    annotationProcessor 'com. Alibaba: arouter - compiler: 1.5.1'
}
Copy the code

Note:

1. For componentize development, all module components (including the main project and library project) should be added to their build.gradle. If they are only added to common components, they will not work.

The API version and compiler version should be the latest. The latest version is available on Github, as shown below:

Step 2: Add an ARouter route annotation (optional)

** * Add annotations to pages that support routing (mandatory) * Note: The path here must have at least two levels, /xx/xx */@Route(path = "/test/RouteActivity")
public class RouteDemoActivity extends AppCompatActivity {
    // Omit the code here....
}
Copy the code

If the path does not match, the framework Toast that the path does not match.

Step 3: Initialize ARouter

Suggested we ARouter inside the Application initialization, so you need to create a custom Application, see the following steps:

Create a new routeApplication. Java class that inherits from Application.

import android.app.Application;

import com.alibaba.android.arouter.launcher.ARouter;

/ * * *@authorAnyang QQ: 15577969 *@version 1.0
 * @teamMeiji software Development Studio *@date2020/11/14 giving * /
public class RouteApplication extends Application {
    //ARouter calls the switch
    private boolean isDebugARouter=true;

    @Override
    public void onCreate(a) {
        super.onCreate();
        if (isDebugARouter) {
            // Prints logs
            ARouter.openLog();
            // Enable debug mode (if running in InstantRun mode, you must enable debug mode! The online version needs to be closed, otherwise there are security risks)
            ARouter.openDebug();
        }
        ARouter.init(this); }}Copy the code

Android :name=”RouteApplication” android:name=”RouteApplication” androidManifest.xml

<application
    android:name="RouteApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
Copy the code

Step 4: Initiate a route operation

 // Simple in-app hops (via URL hops in 'Advanced Usage')
 ARouter.getInstance().build("/test/RouteActivity").navigation();
Copy the code

Vi. Monitor the routing process

 ARouter.getInstance().build("/test/RouteActivity").navigation(this.new NavCallback() {
            @Override
            public void onFound(Postcard postcard) {
                Log.e("Listen to routing process"."OnArrival: Route found");
            }

            @Override
            public void onLost(Postcard postcard) {
                Log.e("Listen to routing process"."OnArrival: No route found");
            }

            @Override
            public void onArrival(Postcard postcard) {
                Log.e("Listen to routing process"."OnArrival: Route jump complete");
            }

            @Override
            public void onInterrupt(Postcard postcard) {
                Log.e("Listen to routing process"."OnArrival: Route intercepted"); }});Copy the code

Initiate routes and pass parameters

// Jump and take parameters
ARouter.getInstance().build("/test/RouteActivity")
                .withLong("id".1)
                .withString("name"."Zhang")
                .withObject("obj".this)
                .navigation();
Copy the code

ARouter provides a number of parameter types, as follows:

// Base type
.withString( String key, String value )
.withBoolean( String key, boolean value)
.withChar( String key, char value )
.withShort( String key, short value)
.withInt( String key, int value)
.withLong( String key, long value)
.withDouble( String key, double value)
.withByte( String key, byte value)
.withFloat( String key, float value)
.withCharSequence( String key,  CharSequence value)

// Array type
.withParcelableArrayList( String key, ArrayList<? extends Parcelable > value)
.withStringArrayList( String key,  ArrayList<String> value)
.withIntegerArrayList( String key, ArrayList<Integer> value)
.withSparseParcelableArray( String key, SparseArray<? extends Parcelable> value)
.withCharSequenceArrayList( String key, ArrayList<CharSequence> value)
.withShortArray( String key,  short[] value)
.withCharArray( String key, char[] value)
.withFloatArray( String key, float[] value)
.withCharSequenceArray( String key,  CharSequence[] value)

/ / Bundle type
.with( Bundle bundle )

//Activity jump animation
.withTransition(int enterAnim, int exitAnim)

// Other types
.withParcelable( String key, Parcelable value)
.withParcelableArray( String key,  Parcelable[] value)
.withSerializable( String key, Serializable value)
.withByteArray( String key, byte[] value)
.withTransition(int enterAnim, int exitAnim)
Copy the code

Routing groups

What is routing grouping?

The ARouter framework is managed in groups and loaded on demand. At compile time the framework scans all the registration pages/services/fields/interceptors, etc., so obviously it is impossible to load them all at run time, it would be too incongruously. Instead of loading any Group, ARouter will load all root nodes at once during initialization, which greatly reduces the number of nodes to be loaded during initialization. For example, some activities are grouped into groups called Demo, and then the demo group is loaded the first time a page within the group needs to be loaded.

@Route(path = "/test/RouteActivity")
Copy the code

The above line of code is the route comment we added earlier, and the first demo is the route grouping. We can also obtain the group in the monitoring routing process. The code is as follows:

 ARouter.getInstance().build("/test/RouteActivity").navigation(this.new NavCallback() {
            @Override
            public void onArrival(Postcard postcard) {
                String group = postcard.getGroup();
                Log.e("Listen to routing process".The current routing group is:+ group); }});Copy the code

The running results are as follows:

Custom route grouping

1. Add the group field to the original annotation

** * Add routes and groups */@Route(path = "/test/RouteActivity", group = "testGroup")
public class RouteDemoActivity extends AppCompatActivity {
    // Omit the code here....
}
Copy the code

2. When initiating a route, enter the group of the route in the second parameter

build(String path, String group)
Copy the code

The example code is as follows:

 // Simple in-app hops (via URL hops in 'Advanced Usage')
ARouter.getInstance().build("/test/RouteActivity"."testGroup").navigation();
Copy the code

3. After adding the user-defined group, the running result is as follows:

10. Fragment routing

Create a Fragment class and add route annotations as follows:

/** * Add Fragment routes */
@Route(path = "/test/ModuleFragment")
public class ModuleCFragment extends Fragment {
    // Omit the code here....
}
Copy the code

We can then route an instance of the Fragment:

// Obtain the Fragment instance through the route
Fragment moduleFragment = (Fragment) ARouter.getInstance().build( "/test/ModuleFragment" ).navigation();
Copy the code

Android and HTML interaction: Jump via URL (advanced usage)

Let’s take a look at the URL link flow chart of the Web:

Create an URLReceiveActivity in the common component. Create an URLReceiveActivity as follows:

Create an Activity that listens for Scheme events and pass the URL directly to ARouter */
public class URLReceiveActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_urlreceive);
        // Distribute URI dataUri uri = getIntent().getData(); ARouter.getInstance().build(uri).navigation(); finish(); }}Copy the code

2. URLReceiveActivity needs to be registered in the AndroidManifest.xml file:

<activity android:name=".URLReceiveActivity">
            <intent-filter>
                <data
                    android:host="m.zy13.net"
                    android:scheme="arouter" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>
</activity>
Copy the code

Note: The host and scheme fields are important. Clicking the URL will start the local Activity based on these two fields.

3. Switch the Android Studio directory mode to Project and create an Assets directory under main:

Create a demo. HTML file in assets directory and write the following HTML code:

<! doctypehtml>
<html>
<head>
    <! -- set the character encoding of the current HTML file -->
    <meta charset="utf-8">
    <! -- Set the compatibility mode version of the browser (let IE work with the latest rendering engine) -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <! -- Declare the Settings related to the current web page display in the mobile browser -->
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <! -- The above three meta tags * must * come first, and anything else * must * follow! -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<body>
<h2>1. Common redirect of the URL</h2>
<p>
    <a href="arouter://m.zy13.net/test/RouteActivity">URL Common Jump</a>
</p>
<h2>2. The URL common jump carries parameters</h2>
<p>
    <a href="arouter://m.zy13.net/test/RouteActivity?name=xiao7&age=18">URL Common redirect carries parameters</a>
</p>
</body>
</html>
Copy the code

Note: arouter://m.zy13.net in a tag represents scheme and host respectively, and /demo/RouteActivity is the annotation of the target Activity.

Add a WebView control to the XML layout of the active page that needs to interact with HTML:

    <WebView
        android:id="@+id/webview"
        android:layout_marginTop="50dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
Copy the code

6. Then load the HTML page in the onCreate() of the Activity, as follows:

private WebView contentWebView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Load the HTML file from the assets directory
        contentWebView = (WebView) findViewById(R.id.webview);
        contentWebView.loadUrl("file:///android_asset/demo.html");
}
Copy the code

In actual development, it is usually used to directly call the url link to interact with HTML, here for simplicity, we directly load the HTML file, the effect is as follows:

If you need to receive UR parameters, you need to call the automatic injection initialization method in the Activity as follows:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;

/** * Add annotations to pages that support routing (mandatory) * Note: The path here must have at least two levels, /xx/xx */
@Route(path = "/test/RouteActivity")
public class RouteDemoActivity extends AppCompatActivity {
    private TextView textView;

    Declare a field for each parameter and annotate it with @autowired
    @Autowired
    String name;

    // Map the different parameters in the URL by name
    @Autowired(name = "age")
    int age;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Automatic injection initialization, ARouter will automatically assign a value to the field, without active fetching
        ARouter.getInstance().inject(this);
        setContentView(R.layout.activity_route_demo);
        / / text
        textView = (TextView) findViewById(R.id.urlTextView);

        textView.setText("The URL parameter is:" + "name: " + name + " age: "+ age); }}Copy the code

Arouter.getinstance ().inject(this).inject(this); arouter.getInstance ().inject(this).inject(this); arouter.getInstance ().inject(this); In this Intent, ARouter can extract the parameters from the URL and insert them into the Intent. In this Intent, ARouter can retrieve the corresponding parameters.

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;

/** * Add annotations to pages that support routing (mandatory) * Note: The path here must have at least two levels, /xx/xx */
@Route(path = "/test/RouteActivity")
public class RouteDemoActivity extends AppCompatActivity {
    private TextView textView;

    Declare a field for each parameter and annotate it with @autowired
    @Autowired
    String name;

    // Map the different parameters in the URL by name
    @Autowired(name = "age")
    int age;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_route_demo);
        / / text
        textView = (TextView) findViewById(R.id.urlTextView);

         /** * Parse the URL parameter and get */ manually
        Bundle bundle = getIntent().getExtras();
        name = bundle.getString("name");
        age = bundle.getInt("age");

        textView.setText("The URL parameter is:" + "name: " + name + " age: "+ age); }}Copy the code

The effect of obtaining URL parameters is as follows:

12. External exposure interface service

The Service referred to here is not the Service among the four components of Android, but the concept of interface development, which is to encapsulate some functions and components into interfaces and provide capabilities externally in the form of interfaces. We can regard the functions to be provided externally as a Service, and the implementation of the Service is the specific business function.

IService has a getData() method in the IService interface. The code is as follows:

public interface IService extends IProvider {
    void getData(Context context );
}
Copy the code

2. Then define an IService implementation class MyService and add a comment as follows:

import android.content.Context;
import android.widget.Toast;

import com.alibaba.android.arouter.facade.annotation.Route;

import net.zy13.module.common.service.IService;

/ * * *@authorAnyang QQ: 15577969 *@version 1.0
 * @teamMeiji software Development Studio *@date2020/11/21 14:14 * /
@route (path = "/service/demo", name = "test service ")
public class MyService implements IService {
    @Override
    public void demo(Context context) {
        Toast.makeText(  context , "This is an exposed interface service!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void init(Context context) {}}Copy the code

Discover interface service

1, define the service object, @autoWired annotate the DEPENDENCY injection interface service, we do not need to know the interface implementation class, as follows:

// Use the dependency injection method to discover the service. Annotate the fields and use them
@Autowired(name = "/service/demo")
IService service;
Copy the code
(Note: if you have multiple implementations of the same interface, you must use byName to discover the service) (if you have multiple implementations of the same interface, you must use byName to discover the service)Copy the code

2, then add annotation initialization, automatic assignment

ARouter.getInstance().inject(this);
Copy the code

The demo() method in the service interface is called

service.demo(this);
Copy the code

The effect is as follows: