-
Notifications
You must be signed in to change notification settings - Fork 8
Interceptor & Rule
Interceptor is quite important in navigation and it is also a important concept of Rabbits. Every processing in the dispatch pipeline is an Interceptor.
You can add custom Interceptor during initialization by invoke addInterceptor(Interceptor)
. Interceptors added in this way will be invoked in every navigation.
Interceptor is an interface. If you want to create an Interceptor, you need override intercept(Dispatcher)
method and return a RabbitResult instance. Dispatcher has a method named dispatch(Action)
, you can fetch the Action object through calling Dispatcher.action()
. The dispatch(Action)
method will internally invoke other interceptors following behind in the dispatch chain.
If you return null
in intercept(Dispatcher)
, Rabbits will internally create a NOT_FINISHED
result and return. That means you can interrupt the navigation and resume the dispatching later, by calling Dispatcher.dispatch(Action)
. There is an example in the Demo project.
If you want an Interceptor takes effect just under some situation, which is more usual, you can add it following by a Rule
instance by invoking this method addInterceptor(Interceptor, Rule)
. Rule is an interface witch can check an Action needs to be intercept or not. To create an Rule is also simple, using Rules
, a factory.
All Interceptors will be stored in a list and the order will be the same as where you add them.
There is another invocation pattern: Rules.ELEMENT().OPERATOR()
, where ELEMENT() can be replaced to scheme()
, domain()
, path()
, query(String)
and OPERATOR() can be replaced to exists()
, is(String)
, contains(String)
, startsWith(String)
, endsWith(String)
, in(String…)
. This invocation chain is meaningful and easy to understand. Here are some example.
// Create a Rule that domain should ends with "kyleduo.com".
Rules.domain().endsWith("kyleduo.com");
// Create a Rule that the value of a query named "param" should equals "1"
Rules.query("param").is("1");
Quite simple, right?
There are other 3 methods for other situation. flags().has(int)
can check whether the flag exists. not(Rule)
, set(Relation, Rule...)
can be used with other Rules to create complex Rules. Here are some examples.
// Create a Rule that the 4th bit from right of flags should be 1.
Rules.flags().has(1 << 4);
// Create a Rule that domain should NOT ends with "kyleduo.com".
Rules.not(Rule.domain().endsWith("kyleduo.com"));
// Create a Rule that domain should ends with "kyledu.com" AND path should starts with "/test".
Rules.set(RuleSet.Relation.AND, Rule.domain().endsWith("kyleduo.com"), Rule.path().startsWith("/test"));
Here is an complete example of Interceptor and Rule.
.addInterceptor(new Interceptor() {
@Override
public RabbitResult intercept(Dispatcher dispatcher) {
dispatcher.action().discard();
return dispatcher.dispatch(dispatcher.action());
}
}, Rules.set(RuleSet.Relation.OR, Rules.query("greenChannel").is("1"), Rules.query("letItGo").is("1")))
This Interceptor works like a green channel. Every action whose url has query named greenChannel or letItGo and it’s value is “1” will not be dispatch to a page, but to the fallback navigator. This feature is useful when you use Rabbits as a bridge between native pages and web pages. A link from web page can open a native page, but if you change your mind and that link should open in Webview, you this feature can save your time.