Router_ A routing framework with full support of single product, component and plug-in, and the necessary knowledge of custom View

After successful registration. Start by:

Router.create(url).open(context); 

The above is the simplest routing configuration and usage. The following will introduce more usage step by step

One to many

For the same page. Multiple non duplicate routing links can be configured:

@RouterRule({url1, url2, url3})
public class ExampleActivity extends Activity {
	...
} 

Get the starting uri in the page

All route initiation events will store the url link of the initiation into the bundle for transmission. You can read it through the following key values:

Uri uri = getIntent().getParcelableExtra(Router.RAW_URI); 

Configure baseUrl

Generally speaking, the routing url defined by an app will have a specific prefix. If it is in a plug-in environment. It is also recommended to define a unique routing prefix for each plug-in. The reason will be explained in the next article on the routing configuration of plug-in environment.

The framework provides RouteConfig annotations. A module can only be configured once and must be configured on the Application subclass:

@RouteConfig(baseUrl="haoge://page/")
public class App extends Application {
	...
} 

The following table shows the matching relationship between the routing prefix and the routing address. The horizontal row represents the routing address configured by RouteRule, and the vertical row represents baseUrl:

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-mnfrtm8q-1630585490709)( https://user-gold-cdn.xitu.io/2018/2/1/1614f0b25fe71152? imageView2/0/w/1280/h/960/ignore-error/1)]

Automatically resolve url parameters

Automatic parameter analysis of Router. It is used in combination with the parcel framework. For the introduction of the parcel framework, please refer to the following link:

Parceler: it's up to you to use Bundle gracefully for data access!

Please note: the parcel framework is not the framework that the Router must rely on. Only after adding this framework, you can use more powerful features.

If not used. All url parameters. Will be resolved to String by default and passed.

  1. Automatic parameter conversion:

first. We first configure the injection entry in the Activity base class, and then configure this entry. The corresponding data will be automatically read from intent. Injected into Arg annotated member variables in subclasses:

public class BaseActivity extends Activity {

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Parceler.toEntity(this,getIntent());
    }
} 

Suppose we currently have the following page:

@RouterRule("haoge://page/example")
public class ExampleActivity extends BaseActivity {
	@Arg
	String name;
	@Arg
	long id;
	@Arg
	boolean isLogin;
	...
} 

You can see. This page contains three properties. Arg annotations are added. At this time, we can use the following link to jump and pass parameters:

Router.create("haoge://page/example?name=haoge&id=10086&isLogin=false").open(context); 

The parameters in the link will be automatically converted according to the type of Arg annotation. After conversion, it is loaded into Intent for transmission. That is, it is equivalent to the following operations:

String url = "haoge://page/example?name=haoge&id=10086&isLogin=false";
Uri uri = Uri.parse(url);
Bundle bundle = new Bundle;
bundle.putString("name", uri.getQueryParameter("name"))
bundle.putLong("id", 
	Long.parseLong(uri.getQueryParameter("id")));
bundle.putBoolean("isLogin", 
	Boolean.parseBoolean(uri.getQueryParameter("isLogin")));

// Start the route and pass the bundle
... 

Parameters of this automatic conversion type. Only basic data types are supported. If the attribute type annotated by Arg is not a basic data type. The automatic conversion is not triggered, and the read String string is directly stored in Intent.

  1. Pass complex parameters

But most of the time, our parameter data is more than the basic data type. For example, ordinary entity bean s. Like a list. So this is the time for parcel to shine!

Parcel has its own JSON data conversion function. The data passed is of non basic data type. This type of JSON string can be passed in the parameter: This is why it is recommended to introduce the parcel framework for use: small and powerful!

Complex parameters need to use the conversion function of Parceler, about data converter. It is also described in the above article. Here I use fastjason's converter:

Parceler.setDefaultConverter(FastJsonConverter.class); 

First, assume that there is a current page, and the parameters need to be transferred to the common entity class User:

@RouterRule("usercenter")
public class UserCenterActivity extends BaseActivity{
	@Arg
	User user;
}

public class User {
	public String username;
	public String password;
	...
} 

Then you can jump through the following link:

// Here, for the convenience of understanding, I do not directly assemble links.
User user = new User("router", "123456");
String json = JSON.toJSONString(user);
// The json string needs to be url encoded first.
String encodeJson = URLEncoder.encode(json);
String url = String.format("haoge://page/usercenter?user=%s", encodeJson);
Router.create(url).open(context); 

You can see that in this way, you can directly transfer specific json data for transmission. Note that for json data in the link. Be sure to encode first. Avoid internal uri parsing exceptions.

Because the user type corresponding to the target page is not a basic data type. Therefore, the value referred to by user will be directly here. After automatic decoding, it is directly put into the Intent and passed to the target page. In the target page, the json conversion will be automatically resolved to the user class using the parser. Complete the transfer of complex parameters

Action routing

As described above. All through a link. Open a corresponding page. This route jump is called page routing.

The Router also supports another route: action route, which has no page Jump. Just for special operations.

For example: add shopping cart, empty shopping cart data, exit login, etc.

@RouterRule("shopcar.clear")
public class ClearShopcarAction extends ActionSupport {
	@Override
    public void onRouteTrigger(Context context, Bundle bundle) {
        // TODO empty shopping cart operation
    }
} 

The empty cart operation can then be triggered via the following link:

Router.create("haoge://page/shopcar.clear").open(context); 

Additional request parameters

The example given above. All data is transmitted directly through a url. But many times. We need to build on this url. Add some additional data for transmission. For example, transition animation configuration, requestCode configuration, Intent.flags configuration, etc

Router.create(url)
	.addExtras(bundle) // Add additional bundle data parameters
	.requestCode(code) // For startActivityForResult
	.setAnim(enterAnim, exitAnim)// Transition animation
	.addFlags(flag)// intent.addFlags(flag);
	.addInterceptor(interceptor)// Add interceptor
	.setCallback(callback)// Set route callback
	.open(context); 

Add route callback

When talking about the routing table, I mentioned that routing is a special startup process, and the startup may not be successful. Therefore, it is natural to have a route callback interface at this time.

The routing callback interface is RouteCallback class:

public interface RouteCallback {
	// When route addressing fails. Trigger this callback
	void notFound(Uri uri, NotFoundException e);
	// When the route is started successfully. Trigger this callback
	void onOpenSuccess(Uri uri, RouteRule rule);
	// When the route fails to start. This callback is triggered. include
	void onOpenFailed(Uri uri, Throwable e);
} 

There are two types of routing callback configurations:

  • Global route callback: all route start events. Will trigger this callback
RouterConfiguration.get().setCallback(callback); 
  • Local route callback: triggered only by the start of the current route.
Router.create(url)
	.setCallback(callback)
	.open(context); 

Routing callback is a very useful feature in page Jump embedding.

Log printing

When the configured Router.DEBUG is true (false by default). The framework will enable internal log output. It is recommended to use BuildConfig.DEBUG to control the log switch, so as to output the log only during development:

Router.DEBUG = BuildConfig.DEBUG 

Logs can be filtered and viewed through RouterLog

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-tc7r9h9r-1630585490711)( https://user-gold-cdn.xitu.io/2018/2/2/16155d64892fbb17? imageView2/0/w/1280/h/960/ignore-error/1)]

Interceptor

As the name suggests: the interceptor is used to perform a series of advance checks during route startup. When the check does not comply with the rules, the route startup will fail.

Take the most classic case: login check

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-bycumn9p-1630585490712)( https://user-gold-cdn.xitu.io/2018/2/1/16150ba1206c981a?imageView2/0/w/1280/h/960/ignore -error/1)]

When you do not use routing to jump, this will lead to a large number of login judgment logic codes written locally. It's hard to maintain. It is also very inflexible. It is convenient to use interceptors to check the login:

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-if9ujnhc-1630585490714)( https://user-gold-cdn.xitu.io/2018/2/1/16150c2dc3758e35? imageView2/0/w/1280/h/960/ignore-error/1)]

The following is a simple login interception implementation:

// Implement RouteInterceptor interface
public class LoginInterceptor implements RouteInterceptor{
    @Override
    public boolean intercept(Uri uri, RouteBundleExtras extras, Context context){
    	// Block when not logged in
        return !LoginChecker.isLogin();
    }

    @Override
    public void onIntercepted(Uri uri, RouteBundleExtras extras, Context context) {
    	// After interception, jump to the login page and pass the routing information to facilitate recovery after login
        Intent loginIntent = new Intent(context,LoginActivity.class);
        // uri is a routing link
        loginIntent.putExtra("uri",uri);
        // All the additional configuration data is loaded in extras
        loginIntent.putExtra("extras",extras);
        context.startActivity(loginIntent);
    }
} 

public class LoginActivity extends BaseActivity {

@Arg
Uri uri;
@Arg
RouteBundleExtras extras;

void onLoginSuccess() {
	if(uri != null) {
		// Login succeeded. Use this method to directly and seamlessly restore route startup
		Router.resume(uri, extras).open(context);
	}
	finish();
}

}

The interceptor function is Router The focus of the framework, and after a long period of iteration. Router At present, there are three kinds of interceptors available, which you can use according to your own needs. Flexible choice of what type of interceptor to use.

#### 1 \. Global default Interceptor:

**Setting mode**: RouterConfiguration.get().setInterceptor(interceptor);

**Scope**: This is the global default interceptor. Will be triggered by all initiated routing events.

**Recommended scenarios**: 

Some checks that require global judgment: such as login check. The interceptor configured here is preferred. Add the corresponding switch control on the.

For example, check the login, if any requestlogin Parameter to enable login checking. Give the login check control to the provider url A place to live.

#### 2 \. Interceptor specially set for a route

**Setting mode**: Router.create(url).addInterceptor(interceptor);

**Scope**: Triggered only by routes created here.

**Recommended scenarios**: Some checks that need to be triggered only when the route is started here: for example deeplink At the entrance of the external link, check whether the external link is legal, etc.

#### 3 \. Interceptor specially set for a target route

**Setting mode**: In configuration RouterRule On the target class of. add to@RouteInterceptor()Notes. Annotations that will need to be configured Class join:

@RouteInterceptors(CustomInterceptors.class)
@RouterRule(rule)
public class ExampleActivity extends Activity {}

**Scope**: When routing url The matched destination route is triggered when this route

**Recommended scenarios**: Check the jump of this page, such as filtering the transfer parameters to avoid unexpected exceptions caused by invalid data.

**The trigger priority of these three interceptors is: Global default > A route > A target route, and if this route has been intercepted by an interceptor. Then subsequent interceptors will not continue to be triggered**

Router Use in a componentized environment
-----------------

For use in componentization Router Frame. Can refer to[Put here github Componentization on demo]( )

Can be combined above demo View with the description below. Achieve more convenient understanding!

Use the routing framework in a componentized environment. The following points should be considered:

### Register multiple routing tables

because Router It does not use automatic registration to register the routing table. Instead, corresponding interfaces and methods are provided to register manually. This configuration method can achieve the effect of dynamically registering multiple routing tables:

RouterConfiguration.get().addRouteCreator(routeCreator);

Therefore, it is used in componentization. Just try to register the routing tables generated by multiple components themselves.

### Activate the annotation processor of the business component

The routing table class is generated automatically at compile time. The scope of the compile time generated framework is only in the current module Yes. So you need to Router The annotation processor is configured and added to each business component respectively, so that each business component can generate its own routing table class using annotations:

annotationProcessor "com.github.yjfnypeu.Router:router-compiler:2.6.0"

In componentization, for the annotation processor used. The recommended approach is to separate all annotation processors that need to be used into a unified annotation processor gradle In the script. Each component then directly apply Apply:

establish processor.gradle: 

dependencies {
annotationProcessor "com.github.yjfnypeu.Router:router-compiler:2.6.0"
... / / all annotation processors are placed in this configuration
}

Then in the component build.gradle Directly through apply from Method to apply this script.

This approach has the following advantages:

1.  Annotation processor due to compile time annotation. Directly to IDE For use. The corresponding code will not be packaged into apk Yes. So don't worry about introducing additional unwanted code apk Yes.
2.  It is convenient for unified control of version upgrade

### Avoid routing table conflicts generated by multiple components

When used in a single product environment. A specific routing table class will be generated during compilation RouterRuleCreator, The package name generated by this class is written dead by default: com.lzh.router.

Therefore, when using in a multi-component environment, each module Specify the package names of different generated routing table classes. Avoid duplicate class conflicts:

@RouteConfig(pack="com.router.usercenter")

Study welfare

[thought map of Android detailed knowledge points (skill tree)]

In fact, there are so many knowledge points about Android development. There are still so many things to ask during the interview. So there is no other trick in the interview. It only depends on how well you are prepared for these knowledge points. So, when you go out for an interview, just look at the stage you have reviewed.

Although Android is not as hot as it was a few years ago, it has passed the era when the four components can find high paying jobs. This can only show that the posts below the intermediate level of Android are saturated. Now there is still a lack of senior engineers. The salary given by many senior positions is really high (there is a lot of money, and you may not be able to find a suitable one), so it is the most important to strive to become a senior engineer.

Here are dozens of sets of interview questions related to the above interview questions, and 19-year interview questions of Jingdong, Xiaomi, Tencent, headlines, Ali, meituan and other companies. The technical points were sorted into videos and PDF s (in fact, it took a lot of energy than expected), including knowledge context + many details.

Due to the limited space, a small part is shown here in the form of pictures.

CodeChina open source project: Android learning PDF + Architecture Video + interview documents + source notes

There are a lot of materials for learning Android online, but if the knowledge learned is not systematic, only a superficial taste when encountering problems and no further research, it is difficult to achieve real technology improvement. I hope this systematic technical system has a direction reference for you.

I'm sure I can find the right one), so it's the most important to strive to become a senior engineer.

Here are dozens of sets of interview questions related to the above interview questions, and 19-year interview questions of Jingdong, Xiaomi, Tencent, headlines, Ali, meituan and other companies. The technical points were sorted into videos and PDF s (in fact, it took a lot of energy than expected), including knowledge context + many details.

Due to the limited space, a small part is shown here in the form of pictures.

[external chain picture transferring... (IMG wyxgozrk-1630585490716)]

CodeChina open source project: Android learning PDF + Architecture Video + interview documents + source notes

There are a lot of materials for learning Android online, but if the knowledge learned is not systematic, only a superficial taste when encountering problems and no further research, it is difficult to achieve real technology improvement. I hope this systematic technical system has a direction reference for you.

Tags: Android Design Pattern

Posted on Thu, 02 Sep 2021 15:29:17 -0400 by unknown1