Android Routing implementation

Source: Internet
Author: User

This article has authorized the public number: Yang (hongyangandroid) in the public platform original debut.

Extra! I am participating in the CSDN2016 Year Blog Star Award, please give me a vote.

Here is my address: http://blog.csdn.net/vote/candidate.html?username=qibin0506

Of course, there are Yang: http://blog.csdn.net/vote/candidate.html?username=lmj623565791.

Note: Every day you can vote Wow, no one has 10 tickets per day ~ ~ ~

Well, the following into today's theme, the first few months have been fortunate to participate in the CSDN organization of the MDCC Mobile Developers Conference, one day down my biggest harvest is to understand the modular development, back then I have been thinking about some of the advantages of modularity, do not say anything else, provide a pluggable way of development is enough for us to be excited for a while ~ Then I began to try some small demo, found that in the modular development of the biggest problem is the communication between components, such as: In the modular architecture, the mall and personal Center is two separate modules, in the development phase, the personal center how to jump to a page of the mall to do? Here we need to introduce the concept of a route. Web development is known that in most Web frameworks URL routing is also a very important part of the framework, if you are not very clear about the concept of routing, you can first look at my this go web development of the URL routing design to understand the concept of the next route, A little explanation here is that routing is the role of forwarding.
A picture to understand the role of the route, because I do not have a local UML tools, the new is still in the download ... 900m+, I'm a little overwhelmed by the speed. So I chose Kolourpaint to manually draw an enchanted picture first to experience.

The motivation to implement a route yourself

What about the development of our Android? If we modular the project, the two components to communicate or jump, we generally build intent way is no longer used, very simple, because in module A is not found in module B in the Class C, which requires us to customize the routing rules, around a bend to jump, To be blunt is to give your class an alias, which we use not to refer to. In fact, when I was ready to implement a route myself, I was Google some solutions, these programs can be broadly divided into two kinds.

  1. Fully implement the route itself, fully encapsulate the jump parameters
  2. Use implicit intent to jump

For both of these ways I summed up, personally think the first way to encapsulate too much, even some of the framework is restful like, such a package is the cost of learning is too high, second, the old project is too cumbersome to change. What about the second way? The use of implicit intent is a good choice, and Android native support, which is also a choice when trying to modular development, but this way only support activity, Service, Broadcastreceiver, scalability is too poor. On top of all the factors, I decided to implement a route myself, referring to the limitations above, our route has a few 2 features.

  1. Easy to get started, the goal is to be able to implement activity, Service, Broadcastreceiver calls with the difference of native mode line code.
  2. Extensibility is strong, developers can add their own routing implementation, not limited to activity, service, Broadcastreceiver.
Try

Before understanding the specific implementation code, we first to understand how the new route is used, is not in line with the above two points, first we first set up three Moduler, respectively, Shell app, mall module Shoplib, BBS module BBSLIB. The app module is our shell, we need to use the app module to pack, and the app is also dependent on shoplib and bbslib, so we can in the app's application to do the route registration.

public  class  app  extends  application  {  @Override  public  void  oncreate  () {super .        OnCreate ();    Setuprouter (); } private  void   Setuprouter  () {router.router (activityrule.activity_scheme +  "Shop.main" , S        Hopactivity.class);    Router.router (activityrule.activity_scheme +  "Bbs.main" , Bbsactivity.class); }}

There are two routes registered here, respectively, the shopactivity of the mall module and the bbsactivity of the BBS module, they are registered through the Router static method method of the class router , two parameters, the first parameter is the routing address (also can be understood as an alias), The class that corresponds to the second parameter. Registration is over, then the next is how to use, we take a look at the mall module how to jump BBS module it.

 Public  class shopactivity extends appcompatactivity {    @Override    protected void onCreate(@Nullable Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); TextView TV =NewTextView ( This); Tv.settextsize ( -); Tv.settext ("Shop!!!");        Setcontentview (TV); Tv.setonclicklistener (NewView.onclicklistener () {@Override             Public void OnClick(View v) {Intent it = Router.invoke (shopactivity. This, Activityrule.activity_scheme +"Bbs.main");            StartActivity (IT);    }        }); }}

The main code is in the click event, we call the Router.invoke method, the first parameter is the current activity, the second parameter is our previous registration of the route, here is very good understanding, the key is to see its return value, here directly return a intent, this is the best ~ Returning intent means that the code below is no different from the way we use native methods! This is in line with the simple purpose we have mentioned above.

As for the 2nd goal, High scalability , you can implement the Rule interface custom route rule, and then call Router.addRule(String scheme, Rule rule) the method to register the routing rules. The rule interface is defined as follows,

/** * Routing Rules Interface <br/> * Created by Qibin on 2016/10/8. */ public  interface  rule  <t , v  > { /** * Add route * @param  patter N Route URI * @param  Klass Route class */ void
      Router (String pattern, class<t> Klass); /** * route call * @param  ctx Context * @param  pattern route uri * @return  {@code V} returns the corresponding return value */  V Invoke (Context ctx, String pattern);}  

To explain, first of all, the two paradigms of the rule interface, the first T is the type of route we registered, such as the activity type used earlier, and the second V is the invoke return value type of the method, such as the intent type used earlier. As for the custom code, here I am. Not provided demo~~~ everyone can try to customize it.

Routing Implementation Code

Next we begin to enter the implementation code-before we come to the code, or a diagram to understand the Router structure of the next.

With the above picture, we look at the code, first we look at the router class, after all, we are in use when we are dealing with router.

/** * Usage: <br/> * <pre> * Step 1. Call the Router.router method to add a route * Step 2. Call the Router.invoke method to route according to the pattern call * < ;/pre> * Created by Qibin on 2016/10/9. */ Public  class Router {    /** * Add custom route rules * @param Scheme Routing scheme * @param Rule Routing rules * @return {@cod E routerinternal} Router real call class * /     Public StaticRouterinternalAddRule(String scheme, rule rule)        {routerinternal router = routerinternal.get (); Router.addrule (scheme, rule);returnRouter }/** * Add route * @param pattern Route uri * @param Klass Route class * @return {@co De routerinternal} router Real call class * /     Public Static<T> routerinternalRouter(String pattern, class<t> Klass) {returnRouterinternal.get (). Router (pattern, Klass); }/** * Route call * @param ctx Context * @param pattern Route uri * @return {@code V} Returns the corresponding return value * /     Public Static<V> VInvoke(Context ctx, String pattern) {returnRouterinternal.get (). Invoke (ctx, pattern); }}

Ha, router code is very simple, mainly to play a similar role as a static agent, the main code is still in RouterInternal , then look at RouterInternal the structure of it.

 Public  class routerinternal {    Private StaticRouterinternal sinstance;/** scheme-> Routing rules * /    PrivateHashmap<string, rule> mrules;Private routerinternal() {mrules =NewHashmap<> ();    Initdefaultrouter (); }/** * Add the default activity,service,receiver route * /    Private void Initdefaultrouter() {AddRule (Activityrule.activity_scheme,NewActivityrule ()); AddRule (Servicerule.service_scheme,NewServicerule ()); AddRule (Receiverrule.receiver_scheme,NewReceiverrule ()); }/*package * * StaticRouterinternal get () {if(Sinstance = =NULL) {synchronized(Routerinternal.class) {if(Sinstance = =NULL) {sinstance =NewRouterinternal (); }            }        }returnSinstance; }}

First RouterInternal is a singleton, a mRules variable to save our routing rules, in the construction we registered three default routing rules, these three routing rules do not want to know is activity, service and Broadcastreceiver. Next look at the other methods.

/** * 添加自定义路由规则 * @param scheme 路由scheme * @param rule 路由规则 * @return {@code RouterInternal} Router真实调用类 */publicfinaladdRule(String scheme, Rule rule) {    mRules.put(scheme, rule);    returnthis;}

addRuleThe method is to add the implementation of the routing rule, and here we add it directly to mRules this HashMap .

privategetRule(String pattern) {    HashMap<String, Rule> rules = mRules;    Set<String> keySet = rules.keySet();    null;    for (String scheme : keySet) {        if (pattern.startsWith(scheme)) {            rule = rules.get(scheme);            break;        }    }    return rule;}

getRuleThe role is to pattern get the rules according to, this is a private method, so in the use of the time do not need to care, its principle is very simple, is based on your pattern match scheme to get the corresponding Rule .

/** * Add route * @param  pattern route uri * @param  Klass Route class * @return  {@code routerinternal} router Real call class */ public  final  <T> routerinternal router  (    String pattern, class<t> Klass) {rule<t,?> Rule = Getrule (pattern); if  (rule = = null ) {throw  new  notrouteexception (" unknown ", pattern);    } rule.router (pattern, Klass); return  this ;}  

This router method is that we add the implementation of the route, we first based on the URI of the route to get the corresponding Rule , and then call the Rule router method, as Rule.router to how the method is implemented, we later see ~

/** * 路由调用 * @param ctx Context * @param pattern 路由uri * @return {@code V} 返回对应的返回值 *//*package*/final <V> V invoke(Context ctx, String pattern) {    Rule<?, V> rule = getRule(pattern);    ifnull) {        thrownew NotRouteException("unknown", pattern);    }    return rule.invoke(ctx, pattern);}

invokeThe method is the code that we execute when we call, the return value T is the type specified in the returned Rule paradigm, for example, the preceding Intent .
In the code, we find that RouterInternal it is actually a management Rule class, the specific call is implemented in each, as Rule mentioned above, Rule is an interface, it has two paradigms, corresponding to the invocation of the invoke return value type and the type of the class we want to route. Let's take a look at how the default number of routing rules is implemented.

For the activity, Service, Broadcastreceiver call, summed up, they are actually the type of return Intent , so we can first build a specified return value is Intent the base type.

/** * Returns the base class for intent routing rules <br/> * Created by Qibin on 2016/10/9. */ Public Abstract  class baseintentrule<t> implements Rule<t,  Intent> {    PrivateHashmap<string, class<t>> mintentrules; Public Baseintentrule() {mintentrules =NewHashmap<> (); }/** * {@inheritDoc} */    @Override     Public void Router(String pattern, class<t> Klass)    {Mintentrules.put (pattern, Klass); }/** * {@inheritDoc} */    @Override     PublicIntentInvoke(Context ctx, String pattern) {Class<t> Klass = Mintentrules.get (pattern);if(Klass = =NULL{throwexception (pattern);}return NewIntent (CTX, Klass); }/** * Throws an exception when no routing rule is found * @param pattern route pattern */     Public Abstract void ThrowException(String pattern);}

routerNot much to say, or to Map add a key value pair, the invoke method, we pass the parameter pattern from the mIntentRules target class, and then build a Intent return, the last throwException is an abstract method, used to call the router class without the exception to throw the ~, you can find , most implementations are implemented here, inheriting this for the activity, BaseIntentRule and specifying the type of class to be routed is activity, and the implementation throwException method is available.

/** * Activity Routing rules <br/> * Created by Qibin on 2016/10/8. */ Public  class activityrule extends baseintentrule<Activity> {    /** Activity Routing scheme*/     Public Static FinalString Activity_scheme ="activity://";/** * {@inheritDoc} */    @Override     Public void ThrowException(String pattern) {Throw NewActivitynotrouteexception (pattern); }}

ActivityRuleFirst inherit BaseIntentRule and specify the paradigm is, the Activity implementation of the throwException method is also very simple, is to throw an ActivityNotRouteException exception, for this exception, we can find in the last source download section of the article to read ActivityRule the implementation, in fact, the other two default Rule implementations are the same ~ Everyone is going to see the code yourself.

In fact, the implementation of a route is very simple, the principle is to give us the class to be routed to define an alias, and then call the place through the alias to invoke. And in the package as far as possible to meet the current user's habits, not too much encapsulation and ignore the users feel.

Well, this article is here, the code in the article can go to https://github.com/qibin0506/Module2Module a modular development of the small demo to find ~

Android Routing implementation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.