In the previous article we analyzed the Arouter routing jump, this article we analyze the Interceptor interceptor.
First, the interceptor also produces the corresponding file during the IDE compilation process. (See Arouter source Analysis 01-Compile the generated file)
public class arouter$ $Interceptors $ $app implements Iinterceptorgroup {
@Override public
void Loadinto (map< Integer, class<? Extends iinterceptor>> interceptors) {
interceptors.put (3, test2interceptor.class);
Interceptors.put (5, test3interceptor.class);
Interceptors.put (7, Test1interceptor.class);
}
As you can see here, the Intercepter are sorted according to the priority, and the levels are put into the interceptors collection from highest to first. So, where are these intercepter loaded into memory?
At the same time, we know that the Interceptor has an init () method that is invoked when the program is initialized, and where the Init () method of the interceptor is executed.
Come back to Arouter.init ()
public static void Init (Application application) {
//...
Hasinit = _arouter.init (application);
if (hasinit) {
_arouter.afterinit ();
}
//...
}
Here's a afterinit method, and we'll take a look at it.
static void Afterinit () {
//Trigger Interceptor init, use ByName.
Interceptorservice = (interceptorservice) arouter.getinstance (). Build ("/arouter/service/interceptor"). Navigation ( );
}
Here, the Interceptorserviceimpl is invoked by route jump, but in the Routing app module build file, there is no/arouter/service/interceptor this routing form, So arouter here is through how to jump it.
Originally, in the Aroute-api, there is a Arouter build file, under this file, and the app module under the same name of the arouter of the first few files (so Arouter.init will also load these routing forms)
Package com.alibaba.android.arouter.routes;
The public class arouter$ $Group $ $arouter implements Iroutegroup {
@Override
the public void Loadinto (map<string, Routemeta> Atlas) {
atlas.put ("/arouter/service/autowired", Routemeta.build (Routetype.provider, Autowiredserviceimpl.class, "/arouter/service/autowired", "Arouter", NULL,-1, -2147483648));
Atlas.put ("/arouter/service/interceptor", Routemeta.build (Routetype.provider, Interceptorserviceimpl.class, "/ Arouter/service/interceptor "," Arouter ", NULL,-1, -2147483648));
}
We'll come back to Interceptorserviceimpl, first call logisticscenter.completion in navigation to invoke the Provider.init () method for initialization.
@Override public void init (final context) {LogisticsCenter.executor.execute (new Runnable () {@Overrid e public void Run () {if (Maputils.isnotempty (Warehouse.interceptorsindex)) {for (Map . Entry<integer, class<? Extends Iinterceptor>> Entry:Warehouse.interceptorsIndex.entrySet ()) {class<? extends Iint
erceptor> Interceptorclass = Entry.getvalue ();
try {iinterceptor iinterceptor = Interceptorclass.getconstructor (). newinstance ();
Iinterceptor.init (context);
Warehouse.interceptors.add (Iinterceptor); catch (Exception ex) {throw new Handlerexception (TAG + "Arouter Init interceptor error!
name = ["+ interceptorclass.getname () +"], reason = ["+ ex.getmessage () +"]);
} Interceptorhasinit = true; Synchronized (Interceptorinitlock) {interceptorinitlock.notifyall ();
}
}
}
});
}
It can be found that, in general, the thread pool. Execute (), in an asynchronous thread, gets all the Interceptor Iinterceptor, invokes their Init method, and adds the interceptor to the Warehouse.interceptors collection.
Got it
Then, continuing in the navigation method, if the Postcard.isgreenchannel is not set to true, then the interceptorservice.dointerceptions execution interceptor is invoked to handle the interception.
Complete the Interceptor init (), and then look at the navigation, interceptor interception,
Final class _arouter {protected Object navigation (final context, final postcard postcard, final int requ
Estcode, Final Navigationcallback callback) {logisticscenter.completion (postcard); Isgreenchannel for ture, saying that you do not need interceptor, to skip Interceptor if (!postcard.isgreenchannel ()) {Interceptorser Vice.dointerceptions (postcard, new Interceptorcallback () {@Override public void Oncontinu
E (postcard postcard) {_navigation (context, postcard, Requestcode, callback); @Override public void Oninterrupt (Throwable exception) {if NULL!
= callback) {Callback.oninterrupt (postcard);
}
}
});
else {return _navigation (context, postcard, Requestcode, callback);
return null; }
}
The
looks at Dointerceptions (), where the interceptor is intercepted, traversing the interceptor list and invoking the Interceptor's process (), and eventually, Callback OnContinue or oninterrupt to continue navigation or terminate navigation according to the result.
@Override public void Dointerceptions (final postcard postcard, final Interceptorcallback callback) {//Check that the Interceptor list is empty
if (Collectionutils.isnotempty (warehouse.interceptors)) {//Wait for interceptor service to complete initialization//... LogisticsCenter.executor.execute (New Runnable () {@Override public void run () {// Countdown Countdown counter Cancelablecountdownlatch interceptorcounter = new Cancelablecountdownlatch (Warehouse.inter
Ceptors.size ());
try {//Execute interceptor operations recursively in another thread _excute (0, Interceptorcounter, postcard);
Wait Timeout interceptorcounter.await (postcard.gettimeout (), timeunit.seconds); The countdown timer is not 0, indicating that there are also interceptors not executed if (Interceptorcounter.getcount () > 0) {//Cancel the navigation th
Is time, if it hasn ' t return anythings. Callback.oninterrupt (New Handlerexception ("The Interceptor ProCessing timed out. "));}
else if (null!= Postcard.gettag ()) {//Maybe some exception in the tag.
Callback.oninterrupt (New Handlerexception (Postcard.gettag (). toString ()));
else {callback.oncontinue (postcard);
The catch (Exception e) {callback.oninterrupt (e);
}
}
});
else {callback.oncontinue (postcard); }/** * Excute Interceptor * * @param index Current Interceptor Index * @param counter Interceptor counter * @ param postcard Routemeta * * private static void _excute (final int index, final cancelablecountdownlatch counter, final Po Stcard postcard) {if (Index < Warehouse.interceptors.size ()) {Iinterceptor Iinterceptor = Warehouse.inter
Ceptors.get (index); Iinterceptor.process (postcard, new Interceptorcallback () {@Override PUBlic void OnContinue (postcard postcard) {//Last interceptor Excute over with no exception.
Counter.countdown (); _excute (index + 1, counter, postcard);
When counter are down, it'll be execute continue, but index bigger than interceptors size, then U know. @Override public void Oninterrupt (Throwable exception) {//Last Interceptor EX
Cute over with fatal exception. Postcard.settag (NULL = = exception? New Handlerexception ("No message."): Exception.getmessage ());
Save the exception message for backup.
Counter.cancel ();
}
});
}
}
So far, that is, to complete the interceptor intercept, the next article, we will resolve the arouter of the function of automatic injection parameters.