Skip to content

Interceptor & Rule

kyleduo edited this page Mar 12, 2018 · 1 revision

Interceptor is quite important in navigation and it is also a important concept of Rabbits. Every processing in the dispatch pipeline is an Interceptor.

Add 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.

Order

All Interceptors will be stored in a list and the order will be the same as where you add them.

Rules

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"));

Complete Example

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.