拦截器
拦截器可以对路由的过程进行介入,改变原本的路由行为。拦截器可以定义在路由的各个阶段,每个阶段也可以定义多个拦截器。通常拦截器以链的形式进行处理,即一个拦截器处理完路由后,会将路由传递给下一个拦截器进行处理,直到所有拦截器都处理完毕。拦截器需要实现 com.tencent.tmf.portal.Interceptor
接口,一个简单的拦截器的示例如下:
public class LaunchInterceptor implements Interceptor {
@Override
public void intercept(Chain chain) {
final AlertDialog.Builder builder = new AlertDialog.Builder(chain.request().context());
builder.setTitle("这是一个请求拦截器")
.setMessage("是否继续打开页面")
.setPositiveButton(android.R.string.yes, (dialog, which) -> chain.proceed(chain.request()))
.setNegativeButton(android.R.string.no,
(dialog, which) -> chain.terminate(Response.create(Response.STATUS_INTERCEPT).setMessage(
"取消打开页面").build()))
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
Interceptor 接口仅包含一个intercept方法,方法接收上一个拦截器传入的 Chain 对象。您可以通过 Chain.request 方法获取到存有路由信息的 Request 对象,并且根据自己的业务逻辑进行处理。业务逻辑处理完毕后应当调用 Chain.proceed 方法将路由对象传递给下一个拦截器;或者是调用 Chain.terminate 方法终止后续的其他拦截器和路由操作,并返回一个表示路由结果的 Response 对象。
全局拦截器
全局拦截器是所有拦截器中优先级最高的。全局拦截器有两种定义方式,通过注解或是使用接口动态添加。使用 @GlobalInterceptor
注解可以声明一个全局拦截器,拦截器会在路由初始化的时候自动加载:
@GlobalInterceptor(name = "static")
public class StaticGlobalInterceptor implements Interceptor {
@Override
public void intercept(Interceptor.Chain chain) {
new AlertDialog.Builder(chain.request().context())
.setTitle("这是一个静态全局拦截器")
.setMessage("点击确定不再提示此拦截器")
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
Portal.unregisterGlobalInterceptor("static");
chain.proceed(chain.request());
})
.setNegativeButton(android.R.string.no, (dialog, which) -> {
chain.proceed(chain.request());
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
注解包含两个参数:
name
:String类型,必选,全局拦截器的唯一标识,用于拦截器的添加和移除,同名的拦截器无法重复添加。priority
:Int类型,可选,表示全局拦截器的执行顺序,值越小的拦截器将会越优先执行,相同priority的拦截器按照添加顺序执行,默认值为-1。
另一种定义全局拦截器的方式是通过接口手动添加:
Portal.registerGlobalInterceptor("dynamic", DynamicGlobalInterceptor.class, -2);
类似注解的方式,手动添加也需要提供三个参数
name
:String类型,全局拦截器的唯一标识,用于拦截器的添加和移除,同名的拦截器无法重复添加。interceptor
:Class类型,需要添加的拦截器类priority
:Int类型,表示全局拦截器的执行顺序,值越小的拦截器将会越优先执行,相同priority的拦截器按照添加顺序执行,默认值为-1。
无论是通过注解添加的还是手动添加的全局拦截器都可以通过接口移除:
Portal.unregisterGlobalInterceptor("dynamic");
启动时拦截器
启动时拦截器的执行顺序在全局拦截器之后,添加的方式是在 launch 之前调用 interceptor
方法添加:
Portal.from(this)
.url(PortalConst.NO_RESULT_ACTIVITY)
.interceptor(new LaunchInterceptor())
.launch(mLaunchCallback);
目的地拦截器
目的地拦截器的执行顺序在全局拦截器和启动时拦截器之后,在定义路由时作为 @Destination
注解的参数绑定到路由目的地上:
@Destination(url = PortalConst.INTERCEPTOR_ACTIVITY,
launcher = Launcher.ACTIVITY,
interceptors = {DestinationInterceptor.class},
description = "Portal演示")
public class InterceptorActivity extends TopBarActivity {
@Override
protected View getContentView() {
return LayoutInflater.from(this).inflate(R.layout.activity_interceptor, null);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTopBar.setTitle("路由演示子页面C");
Bundle params = getIntent().getExtras();
if (params.containsKey("param")) {
((TextView) findViewById(R.id.parameter)).setText("拦截器输入的内容: " + params.getString("param"));
}
}
}
@Destination
注解包含换一个 interceptors
参数,类型为一个拦截器类数组,可以通过这个数组为路由的目的地设置多个拦截器。目的地拦截器将按照数组中定义的顺序执行。