1. Overview of ARouter’s principle
ARouter is a routing framework developed by Ali open source to help the componentized transformation of Android APP. It can realize the jump between activities of modules that are not dependent on each other in the same project.
ARouter’s routes, parameters, and interceptors are annotated. Annotations are used in Retrofit, Dagger, and EventBus.
ARouter’s jump is based on the RouterMap routing table. RouteProcessor generates the routing table and LogisticsCenter or RegisterTransform loads the routing table.
Annotations are divided into runtime annotations and compile-time annotations. Compile-time annotations rely on the Annotation Processing Tool APT (Annotation Processing Tool) to scan and process annotations at compile time. With APT, we can write much less template code. At compile time, the compiler examines subclasses of AbstractProcessor, calls their process() method, and passes the annotated elements to process(), This allows us to generate a new Java class file in the process() function.
RouteProcessor is an annotation processor, a subclass of AbstractProcessor. In RouteProcessor’s process() method, the parseRoutes() method is called, and the parseRoutes() method generates Java code using the JavaPoet API, The specific code is the Class information of the Activity Class. In addition to RouteProcessor, ARouter also has the AutowiredProcessor, a parameter annotation processor, and the InterceptorProcessor, an InterceptorProcessor, which works in the same way as RouteProcessor.
After calling the Build () method of ARouter, the Postcard object will be returned. The navigation() method we call is the Postcard’s Navigation () method. The Postcard’s navigation() method will be called into the navigation() method of _ARoute. In this method, the preprocessing service will be processed first and LogisticsCenter will fill the Postcard with information. If LogisticsCenter does not find the corresponding route, it follows the logic of the demotion policy. If LogisticsCenter does not find the corresponding route, it determines whether to follow the green channel. If LogisticsCenter does not follow the green channel, the interceptor chain decides whether to jump. After the jump is complete, if the jump callback is set, LogisticsCenter will call this callback.
PretreatmentService is a PretreatmentService interface, which can be used by defining a class that implements this interface and adding a @route annotation to this class. PretreatmentService is used to make a judgment before loading the routing table when performing some jumps.
A degrade policy is provided to assist users to achieve a degrade interface. For example, it provides an error message or error log for a separated Route. A degrade policy provides a class that provides this interface and adds the @Route annotation to the degrade interface.
The purpose of the greenChannel is to determine whether to go through the interceptor chain. For example, if we define a login interceptor, but a page does not need to make this determination, it can go through the greenChannel() method after calling the build() method.
Interceptor is a class that adds the @interceptor annotation and implements the IInterceptor interface. Through Interceptor, we can do some logic such as login status judgment.
The jump callback is essentially a NavigationCallback interface or NavCallback abstract class passed to the Navigation () method.
ARouter generates routing tables in two ways, either by run-time reflection or by compile-time insertion.
The init() method of LogisticsCenter is called in ARouter’s init() method, The init() method of LogisticsCenter determines whether the routing table has been inserted at compile time based on the value of registerByPlugin, and if not, registers the routing table information through run-time reflection.
Runtime reflection is the Class information in the dex file loaded by ClassUtils in the init() method of LogisticsCenter, and then initialized by reflection and saved to the Warehouse.
Dex file is an executable file on the Android platform, similar to the exec file in Windows. Each APK installation package contains Dex file, which contains all the source code of APP. After decompilation, you can see the corresponding Java source code.
Compile-time insertion is when RegisterTransform reads the routing table information from the Jar file. RegisterTransform RegisterTransform inherits from the Transform class. A Transform is an Android API used to modify resources such as classes. Each Transform is a Gradle task. Resources such as JARS, aar and Resources can be read and processed, and user-defined transforms are inserted at the top of the Transform queue.
The Transform API does a lot of things, like staking all the class files and doing UI, memory, and network performance monitoring. You can also tweak the logic of a third-party library by modifying the contents of its class file. You can also insert the current line of code into the Log to make it easier to locate problems. You can also dynamically proxy any class. You can also implement code that prints out the input and output parameters of a method.
2. ARouter profile
ARouter is a routing framework developed by Ali open source to help the Android App to be compontized. It is a middleware that provides routing functions for pages and services on the Android platform and can realize the jump between activities of different modules. ARouter is characterized by flexibility and helps decouple projects.
Flexibility refers to the fact that in complex business scenarios, many functions are dynamically configured by the operations staff. For example, if the e-commerce system needs to deliver an activity page, the App does not know the specific target page of the activity in advance, but if the page mapping is made in advance, it can be configured freely.
Helping decouple means that as the volume of business grows, our projects will have more code and collaboration between developers will become more complex, and the common solutions to this problem are plug-in and componentization. The premise of plug-in and componentization is decoupling of code, and then maintaining the dependencies between pages, which requires a general mechanism.
ARouter supports direct resolution of standard URL jumps, use in multi-module projects, adding multiple interceptors, acting as a standalone dependency injection framework, configuring transition animations, generating routing documents, and more.
3. ARouter Architecture Overview
The ARouter project contains four modules: API, Compiler, Gradle Plugin and Annotation.
The API module consists of launcher, Core, Exception, Thread, Facede, utils, and Base submodules.
Launcher, which contains the launcher ARouter, and core, which contains classes like LogsticsCenter and Warehouse. Exception contains some exception classes. Thread package contains the CancellableCountDownLatch, ARRouter interceptor chain is in the child thread, used to it. The Facede module contains interfaces such as NavigationCallback and IInterceptor. Utils contains utility classes such as ARouter’s custom log printer. The base package contains only one UnitqueKeyTreeMap for interceptors;
ARouter’s Compiler module contains classes for generating routing tables, The annotation processors corresponding to @Autowired, @Interceptor, and @Route annotations are AutowiredProcessor, InterceptorProcessor, and RouteProcessor respectively The Compiler package.
The Register Plugin module contains the RegisterCodeGenerator and RegisterTransform. If we use ARouter’s routing table loading Plugin, the routing table will be loaded by the Register Plugin.
The Annotation module contains only annotations like @AutoWired and enumerated classes like RouteType.
4. ARouter
The rest of the code will be uniformly demonstrated by Kotlin.
1. Add dependencies and configurations
2. Declare a path
When using ARouter, you declare the path to the target with the @route annotation. Note that the leading slash is not missing, and the path must have at least two levels.
Group is optional. In this code, ARouter will group the path. If the group is not passed, ARouter will set Goods as the group of the path, otherwise Taobao will be the group of the path.
3. Initialize ARouter
Printing logs and enabling debug mode must be written before init(), otherwise these configurations will not be valid during initialization.
4. Jump
During the jump, we can also upload group. For example, if Taobao is uploaded in this example, it will jump to the commodity details page under Taobao group; otherwise, it will jump to the commodity details page under Goods group.
5. Postcards of Beijing
Before talking about ARouter’s routing table generation mechanism, let’s take a look at RouteMeta and Postcard, which are important in the process of routing table generation and loading. When we call ARouter.getInstance ().build(), we are actually creating a Postcard object. Methods like withXXX() and navigation() are its methods. The navigation() method of the Postcard ends up calling the navigation() method of _ARouter. The implementation of _ARouter will be explained later.
According to the note of the Postcard, it is a container for the road map. It can be thought of as a Postcard with recipient information and specific contents.
Postcard is a reflection of RouteMeta, which is the content of a routing table. The Postcard contains information like transfer parameters and animations upon arrival. Let’s take a look at RouteMeta.
5.1 RouteMate
A RouteMeta contains basic information about a jump route, which by its name is the meta information of the route. Meta information is information about the message, and a RouteMeta contains the following fields.
- Route type type
- Route rawType rawType
- The end destination
- Path the path
- Route set group,
- Priority int
- Mark extra
- Parameter type paramsType
- Route of the name
- Injection configuration injectConfig
1. Route type
The RouteType RouteType is an enumerated class that has the following types.
-
Activity
-
Service
-
Provider
That is, custom service IProvider;
-
ContentProvider
-
Fragment
-
Broadcast
-
Method
-
Unknown
Unknown route;
Service, Broadcast, and Method are not implemented.
2. Route primitive type
The rawType of the route is Element, which will be explained later. The only thing you need to know here is that Element contains information about the target Class, which is set by the RouteProcessor.
3. The finish
The destination is the Class that declares the @Route target, such as the Class of the target Activity and Fragment. This information is also set by the RouteProcessor.
4. Paths and route groups
If we specify only the path in @route, such as path = /goods/details, then goods is the group and details is the path.
If we set the group value of @route, such as group = Taobao, then the path group is Taobao.
5. The priority
The priority cannot be set in @route. It is for interceptors. The lower the value of priority, the higher the priority of interceptors.
The interceptor chain implementation class is InterceptorServiceImpl, which gets interceptors in order of priority when calling the interceptor’s onInteceptor() method.
6. Mark
This extra is the mark of the routing document RouteDoc, which contains routing and service-related information. By default, the corresponding file will not be generated. If you want to generate the file, you can set the generated document in the annotation processing parameter.
-
Add parameters
If we want to view routing documents, we can add to AROUTER_MODULE_NAME:
AROUTER_GENERATE_DOC: “enable”
-
Document path
build/generated/source/apt/(debug or release)/com/alibaba/android/arouter/docs/arouter-map-of-${moduleName}.json
The general content of the routing document is as follows.
7. Parameter type
ParamsType: ARouter gives an enumeration value for the paramsType specified by the jump, and then calls getXXXExtra() of the Intent based on the specified type.
5.2 it
The following fields are contained in the Postcard.
- Uniform Resource Identifier (URI)
- Tag the tag
- The ginseng mBundle
- Logo flags
- Timeout duration
- User-defined service Provider
- Whether to use the greenChannel greenChannel
- SerializationService serializationService
- Transition animation optionsCompat
- Enter and exit the animation enterAnim/exitAnim
Let’s look at what these fields do.
1. uri
In ARouter, we can use the URI as a path jump, and ARouter will replace the path with the PathReplaceService service. This service has no default implementation, and if we need to replace different paths for different protocols and hosts, we will implement this service ourselves.
If we didn’t implement the service, scheme and host addresses would be meaningless, and ARouter would only resolve the path and parameters by default. In the above example, the path is moduleA/second and the parameter is name= Lao Wang.
2. tag
The tag is used to get exception information in the Interrupt () method of NavigationCallback.
In the interceptor chain InterceptorServiceImpl, when we call onInterrupt() in our custom interceptor, the InterceptorServiceImpl creates a HandlerException, Using it as the Postcard’s tag, and then listening for the jump result, you can retrieve the Postcard’s tag information in the onInterrupt() method to get the exception information.
If the exception we pass in the interceptor is empty, HandlerException() defaults to “No message.”
3. mBundle
When we call methods like withString() to set the data to be passed to the jump target, that data is in the mBundle.
4. flags
When we call withFlag() to set the Activity’s start flag, this flag is assigned to the Flags field.
5. timeout
The chain of interceptors handles jump events in CountDownLatch. The default timeout is 300 seconds, or 5 minutes, so we don’t want to do time-consuming operations in interceptors.
6. provider
When we implement the custom service, the parameter annotation processor AutowiredProcessor creates a class for each path that implements the Syringe ISyringe interface. In the Inject () method of this class, Arouter.getinstance ().navigation(xxxService.class). When LogisticsCenter finds that this is a Provider, it creates a Provider instance by reflection. Then set it to the Postcard and go to the Postcard.
7. greenChannel
The so-called green channel is the channel that will not be processed by the interceptor chain. Custom services IProvider and Fragment are the green channel.
If we want a jump operation to skip the interceptor, we can call the greenChannel() method before navigation().
8. serializationService
When we call withObject(), ARouter gets our own custom SerializationService, SerializationService, and then calls its object2Json() method, We convert the data to a String and put it in the bundle.
6. Principle of generating the ARouter routing table
After seeing RouteMeta and Postcard, let’s take a look at the routing table generation process for RouteProcessor.
6.1 Annotation Processing Process
AndroidJavaCompiler (AndroidJavaCompiler, AndroidGradle, AndroidJavaCompiler, AndroidJavaCompiler, AndroidGradle, AndroidJavaCompiler, AndroidJavaCompiler) Javac then calls annotation processors such as RouteProcessor to process annotations.
6.2 Route Resolution Process
RouteProcessor’s handling of classes that declare @Route annotations can be roughly divided into the following four steps
- Get routing elements
- Example Create route meta information
- Group the routing meta information
- Generating routing Files
1. Obtain route elements
The Element here refers to the Element in the Javax package, which represents Java language elements such as fields, packages, methods, classes, and interfaces.
The process() method receives annotations, the current processor’s annotations, and roundEnv, the runtime JavacRoundEnvironment.
JavacRoundEnvironment has a getElementsAnnotatedWith() method that RouteProcessor first uses to get elements when working with annotations.
2. Create route meta information
By routing meta information, I mean a RouteMeta. RouteProcessor associates activities, providers, services, or fragments that declare the @Route annotation with a RouteMeta.
When the element type is Activity, the RouteProcessor iterates over the Activity’s child elements, the Activity’s member variables, and puts them into the injectConfig of the injected configuration RouteMeta. When we configure to generate a routing document, the RouteProcessor writes injectConfig to the document and then groups the meta information.
3. Group the routing meta information
There is a groupMap in the RouteProcessor, and once a RouteMeta is created, the RouteProcessor groups the different Routemetas into the groupMap.
For the path /goods/ Details example, if we don’t set the group value in @route, the RouteProcessor will refer to goods as the Group of the RouteMeta.
4. Generate a routing table
Once RouteProcessor has grouped RouteMeta, it generates the Group, Provider, and Root routing files that make up the routing table using JavaPoet, Square’s open-source code-generation framework.
After the routing files are generated, the logistic center LogisticsCenter needs to populate the routes and providerIndex indexes in the Warehouse Warehouse with these files, and then jump based on the routes and index when jumping.
We’ll talk about LogisticsCenter and Warehouse later, but let’s take a look at the routing file.
RouteProcessor routing file generated in the build/generated/source/kapt/debug/release/com/alibaba/android/arouter/routes.
Taking a routing file in the ARouter sample project as an example, the RouteMeta created by RouteProcessor would be converted to something like this.
The other routing files are much the same, all populated by RouteProcessor.
7. ARouter jump principle
After looking at the routing table generation process, let’s take a look at ARouter’s jump principle.
When the Postcard’s navigation() method is called, the Postcard’s navigation() method will be called by _ARouter and then the _ARouter will load the routing table. Here is the processing flow of navigation().
The _ARouter navigation() method has the following two overloads.
navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback)
navigation(Class<? extends T> service)
Copy the code
7.1 navigation ()
The first overload is for jumping, and the second overload is for creating a service. Let’s look at the implementation of the first overload.
_ARouter’s navigation() method looks like this.
_ARouter’s navigation() will first determine whether to continue processing according to the pre-processing service we have implemented, otherwise the jump process will be interrupted.
If the preprocessing service returns true, the navigation() method will load the routing table and populate the Postcard with information about the RouteMeta, such as destination, This operation is done by the LogisticsCenter LogisticsCenter.
If LogisticsCenter encounters an exception in the process of perfecting the postcard, for example, it cannot find the target corresponding to the path, then it will call the downgrade strategy, and we can display error messages in the downgrade strategy.
-
The interceptor chain
After the postcard completes the information, navigation() passes the jump event to the interceptor chain;
-
Jump by type
When the interceptor chain processing is complete and the jump is not broken, navigation() will jump to a different page or invoke a custom service based on the path type;
1. Implement pre-processing service
The pre-processing service allows us to determine whether the PostCard post needs to be processed independently before the ARouter jumps to the PostCard by returning false in onPretreatment().
2. Pre-processing service processing process
In navigation(), the onPretreamtn() method of the preprocessing service is first called to determine whether to proceed further or not. If false is returned, no further processing is performed, i.e. no jump, etc.
7.2 Improving postcards
After invoking the preprocessing service, _ARouter uses LogisticsCenter to load the routing table, which is the routing file generated by RouteProcessor.
1. Obtain the route meta information
When _ARouter is initialized, LogisticsCenter is initialized as well. The LogisticsCenter initialization method reads the routing table created by RouteProcessor and puts it into the corresponding index index.
With the index, when _ARouter calls the LogisticsCenter completion() method, you can use the index to get the routing meta information from the Routes in Warehouse.
If LogisticsCenter does not find the RouteMeta based on the index, then the routes have not been filled, so LogisticsCenter gets the RouteMeta of the group. Then fill the path under the Group into routes, and call completion() again to get the information for the filled postcard.
Indexes are loaded when LogsticsCenter is initialized, and we’ll talk about routing table loading later.
2. Fill in the postcard information
When we called the ARouter.getInstance().build() method, we created a Postcard, but the information about it is incomplete.
For example, the Destination field in the Postcard indicates the Class information of the destination. A destination is an Intent that is used as a destination. Destination is the second parameter in the constructor of the Intent.
The LogisticsCenter is responsible for filling the postcard with destination information obtained from the routing table. With a complete postcard, the next jump can be performed.
3. Initialize the Provider
After filling in the Postcard information, LogisticsCenter will perform operations on the Postcard based on its type. If the Postcard is a Provider, the LogisticsCenter will call the Provider’s initialization method and set the Postcard to a green channel.
If it is a Fragment, the Postcard is set to a green channel only. If it is of other types, it is not. By green channel, I mean that the Provider and Fragment skip the interceptor chain.
2.1.3 Downgrade Policy
The so-called downgrade strategy, in fact, when the jump fails, we can jump to another page, such as a jump failure prompt page.
If ARouter encounters an anomaly while perfecting the postcard’s message,
1. Process the degradation policy
After calling the pre-processing service, Navigation () will populate the PostCard content via LogisticsCenter. If an exception is encountered during the filling, the downgraded service will be called, about which later.
2. Customize the degrade policy
When you customize your degrade strategy, be aware that the context might be empty, so use context, okay? .
7.3 the interceptor
Interceptors can be used to handle events during jumps, such as login checks, which are executed between jumps and multiple interceptors are executed in priority order.
1. Implement interceptors
When implementing an interceptor, we call either the onContinue() or onInterrupt() methods, at least one of which needs to be called, or the route will not continue.
-
onContinue()
This method indicates that the processing is complete, and control is exchanged to ARouter;
-
onInterrupt()
When we feel there is a problem, we can interrupt the routing process by passing an exception with the onInterrupt() method.
2. Interceptor processing flow
Navigation () after completing the Postcard’s information, it will determine whether the Postcard is handled through a green channel. A green channel is a channel that does not pass through the interceptor chain. The implementation of the interceptor chain will be discussed later.
In completion() of LogisticsCenter, the Provider and Fragment routes are set as green channels. If we want the target page to skip the interceptor chain, You can call the greenChannel() method before the navigation() method.
7.4 Jump by Type
When the interceptor is processed, the _navigation() method is called in navigation(), which is the specific jump method.
In this method, the Postcard’s RouteType RouteType is used to determine how to jump to the Postcard.
1. Activity
When RouteType is an Activity, the process of starting an Activity is the same as when we normally start an Activity: creating an Intent, passing ina destination, setting a fragment, rewriting an animation, etc. StartActivity () is finally called to launch the target page.
2. Fragment / Broadcast / ContentProvider
When the jump target is Fragment, Broadcast, or ContentProvider, the reflection instance is created by destination. If Framgent ARouter is Framgent, it sets the parameters to pass to the target Fragment. Then return the instance.
3. Provider
If the redirect is directed to a Provider, then the redirect is directed to an ARouter custom service.
7.5 Jump Callback
When calling navigation(), we can pass NavigationCallback in navigation() to listen for events that occur during the jump.
-
onLost()
The jump target cannot be found.
-
onFound()
The jump target is found.
-
onInterrupt()
Interceptor breaks jump;
-
onArrival()
The jump target has been opened.
NavigationCallback Is an abstract class in ARouter that implements NavigationCallback. NavigationCallback is an abstract class in ARouter that implements NavigationCallback. Using NavCallback does not force us to override all methods, just onArrival().
8. Principle of loading ARouter routing table
Loading the routing table is actually loading the class files generated by RouteProcessor.
When we call ARouter’s init() method, ARouter will call LogisticsCenter’s init() method, and in the init() method, LogisticsCenter will determine whether the current routing table loading method is a plug-in, If not, the routing table is loaded from Dex; if yes, the plug-in loads the routing table from the Jar.
Let’s see how to load the routing table through Dex.
8.1 Loading a Routing Table from Dex
The process of loading a routing table through classes can be roughly divided into four steps: reading the Dex file, reading the routing table from the Dex file, saving the routing table locally, and saving the routing information to the index.
Reading the Dex file refers to the ClassUtils used to read the routing table when LogisticsCenter finds that no plug-in is loading the routing table. Here said the routing table, is actually RouteProcessor generate good class file name of the class, and read the Dex file, from the source directory (applicationInfo. SourceDir) reads the base apk path, Then build a DexFile(path) with this path.
Read from Dex file refers to the routing tables ClassUtils will use DexFile read the class information in the apk, and then judge whether the package name of the class for the com. Alibaba. Android. Arouter. Routes, If it is, it is the routing file generated by ARouter’s annotation handler, which adds the matching classes to the list and returns the list to LogisticsCenter.
Saving the routing table locally means that when LogisticsCenter gets the class names generated by the annotation processor from ClassUtils, it saves those class names in SharedPreferences. Next time, depending on the App version, if it is not a new version, Load the class name locally, otherwise read it using the ClassUtils.
Saving routing information to index means that after LogisticsCenter saves the routing table to SharedPreferences, It determines whether the class is IRouteRoot, IInterceptorGroup, or IProviderGroup based on the suffix of the class name, and loads the contents of the class file into the index for each class.
8.2 Loading a routing table from a Jar
If we want to shorten the initialization time of ARouter, we can use ARouter’s Gradle plugin. This plugin automatically loads the routing table, so that ARouter does not need to read the class information when it is initialized, thus shortening the initialization time.
The Register plug-in loads the routing table from the Jar file as follows.
When we run our App, Gradle calls the ARouter Register plugin that we depend on. This plugin is executed from the apply() point in the PluginLaunch. PluginLaunch determines that routing table information is loaded only when the running project is Applicaiton.
The Android Gradle plugin includes a Transform API that allows third-party plug-ins to process compiled class files before converting them to dex files. ARouter’s Register plugin implements a RegisterTransform.
When Gradle’s TaskManager TaskManager executes TransformTask, RegisterTransform’s transform() method is executed. In the transform() method, we receive a TransformInput collection from TaskManager. Using TransformInput, we get the Jar and Class files that Gradle generated for our project. Includes files generated by RouteProcessor.
When RegisterTransform gets the Class file, it uses the ScanClassVisitor in ScanUtils to access the bytecode data in the Class, including the package name and Class name. ScanClassVisitor is a subclass of ClassVisitor, which can change and modify bytecode, When ScanClassVisitor finds that the current Class implements the IRouteRoot, IIntercetorGroup, or IProviderGroup interface, All three interfaces add the Class name of the current Class to the classList of ScanSetting.
After RegisterTransform has initialized the classList in ScanSetting, RegisterCodeGenerator is used to insert the code into the Jar file.
In RegisterCodeGenerator insertInitCodeIntoJarFile () method, the Jar file into JarFile object, and then get the JarEntry JarFile, Find LogisticsCenter and insert the routing table into the loadRouteMap() method of LogisticsCenter, as shown below.
-
Jar file path
build/intermediates/transforms/com.alibaba.arouter/debug/41.jar
9. ARouter advanced usage and precautions
1. The refs
2. Parse the parameters
There are a few things to note when using the @Autowired annotation.
Note here that if the Activity or Fragment is written in Kotlin, the @jVMField is added to the field to provide getter() and setter() for ARouter to use.
Key cannot be null because it will be taken as the default, otherwise a null pointer exception will occur. That’s because when ARouter gets parameters with methods like getLongExtra() of the Intent, those methods default not to wrapper types like Long, but to primitive types like Long.
When a List and Map are passed with withObject(), the object received cannot be marked with the specific implementation class type. It should be declared as List or Map, otherwise it will affect the determination of the type in the serialization. Other similar cases need to be handled in the same way.
If you find that you cannot receive the parameters you want, you can make a breakpoint in the AutoWired () method of AutowiredServiceImpl to see what exception is encountered.
If a compilation fails while using ARouter and you don’t know why, you can use the command gradle aseembleDebug — stackTrace to view a detailed compilation log.
3. Implement the serialization service
ARouter allows us to set up serialization services. If we need to pass custom objects, we simply create a new class that implements SerializationService with the @Route annotation. We can assign different groups to the service, like yourServiceGroupName below.
4. Customize services
In addition to services such as serialization, ARouter also allows us to implement custom services by implementing the IProvider interface.
First declare the interface.
Then implement the interface.
ARouter discovers services either through dependency injection or through dependency lookup. Dependency injection is recommended, as shown below.
HelloService and helloService2 discover services through dependency injection, which means annotation fields can be used without active retrieval.
If the name attribute is not set, the service is discovered using byType by default. HelloService is byType.
After the name is annotated in the Autowired annotation, the corresponding field will be injected using byName.
When there are multiple implementations of the same interface, the service must be discovered using byName, which helloService2 is.
Here is the code to discover the service by dependency lookup. Actively discover and use the service, helloService3 is byName and helloService4 is byType.
)
5. Go to the URL
If we want the application to handle the external URI directly, we can simply configure it in the manifest file and pass the URL to ARouter.
First set the host, declare the Activity’s action and category in the Manifest, and add the host and protocol scheme to the data tag.
Then create an Activit Y to listen for Scheme events and pass the URL directly to ARouter.
6. Set transitions
ARouter provides the withTransition() method to animate the jump
7. Get fragments
When retrieving a Fragment, note that null is returned if the Fragment cannot be found. .
Other 10.
If you want to exchange Android development related issues, welcome to add my wechat oushaoze2015 to discuss, please note “digging gold” when adding.
The resources
- ARouter document
- ARouter uses the tutorial
- Deeper understanding of Transform
- ASM framework learning (2)-ClassVisitor