当前项目在做模块化、组件化的开发实践,这其中就少不了路由框架的使用。项目选用阿里的
ARouter
路由框架,最近在实现登录拦截功能时候,遇到一点小问题,特此记录。
Inteceptor
实现,官方文档按照官方文档以及Demo
的代码示例,设置场景为某个Activity
需要登录方能调用,就需要在该Activity
上添加路由以及配置响应标记extra
其中为int
值
//路由注解,以及extra标记为该页面需要登录
@Route(path = RouterPath.ROUTER_PATH_WEB_ACTIVITY, extras = 10086)
class WebActivity : BaseWebActivity() {
companion object {
const val INTENT_EXTRA_URL = "url"
}
//注解,ARouter url传递来的参数名,可以通过@Autowired(name=“urlParam”)字段改写本地的名称,java中需要public,koltin中需要lateinit,
@Autowired(name = "url")
lateinit var urlStr: String//用于显示web的url
//覆写基类中的成员变量,并赋值
override val urlParam: String
get() = urlStr
override fun onCreate(savedInstanceState: Bundle?) {
ARouter.getInstance().inject(this)
super.onCreate(savedInstanceState)
}
}
路由框架中inteceptor
都是AOP
切面编程的,在ARouter
中一般的路由跳转都会经过拦截器的。除非在ARouter.getInstantce()
进行跳转的时候标记了greenChannel
。
登录拦截器LoginInteceptor
@Interceptor(priority = 9, name = "LoginInteceptor")
class LoginInterceptor : IInterceptor {@SuppressLint("CheckResult")//Single的rx结果,不处理了,
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
//拦截操作,去调用登录
if (postcard != null && postcard.extra == ARouterConstants.AROUTER_POSTCARD_EXTRA_NEED_LOGIN) {
val isLogin = SPUtils.getInstance().getBoolean("isLogined")
if (isLogin) {
callback!!.onContinue(postcard)
} else {
//跳转登录
//拦截器运行在ARouter的子线程池中,若要启动activity,必须切换到主线程操作。而且,ARouter所有一般的跳转都会走拦截器,
//如此,就会形成死循环,所以跳转登录,就需要greenChannel,忽略拦截
Single.just(0)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer<Int> {
ARouter.getInstance()
.build(RouterPath.ROUTER_PATH_LOGIN_ACTIVITY)
//拦截跳转web H5的时候,后续登录成功后,继续跳转,需要这个url
.withString(
WebActivity.INTENT_EXTRA_URL,
postcard.extras.getString(WebActivity.INTENT_EXTRA_URL)
)
.greenChannel()
.withFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.navigation()
})
callback!!.onInterrupt(null)//路由中断
}
}
}
override fun init(context: Context?) {}
}
登录拦截器的实现,如上。其中需要注意点:
process
中,就不要再用ARouter
的方式调用登录,因为每次路由都会走拦截器,这就形成了死循环。如果要用,就要添加.greenChannel()
来规避拦截。Inteceptor
都是运行在ARouter
内部的一个线程池中,在这里不要切换到主线程才能生效。(个人测试如此,或许有其他解决方式)callback
的onInterrupt
或者onContinue
extra
的int
标记值,所以这里用postcard.extra
取值如上可以简单使用,是官方文档,也是Demo
中的示例方式。然而多数情况下的业务需求,并不是这样。比如WebActivity
有些传来的URL
界面是需要登录,有些则不必登录,而在WebActivity
上配置了extra
就意味着每种URL
都要拦截。
1、解决方案可以是配置
CommonWebActivity
继承WebActivity
,配置不同的路由,并且不添加extra
标记。这就需要,在URL
传递方,来根据是否登录,调用不同的路由。2、或者那些不需要登录拦截的
URL
调用时候,都配置greenChannel
来规避拦截,但是如果有多组拦截器策略,就会被同时忽略掉了。
如上的解决方案,都少都有些不符合生产业务场景。我们想要的是可以在代码中动态配置哪些跳转需要登录拦截,或者其他拦截标记,哪些不需要。extra
的标记,其实在ARouter.getInstance().build("route—path")
之后,会生成postcard
的对象,这个就是本次路由跳转信息的一个载体。postcard.setExtra(Int)
有这个api
,所以就想:
val postcard = ARouter.getInstance()
.build(RouterPath.ROUTER_PATH_WEB_ACTIVITY)
//设置本次跳转的extra标记,想要每次不同的调用,配置不同的extra标记,
postcard.extra=10010
//继续原有跳转
postcard
.withString(
WebActivity.INTENT_EXTRA_URL,
"http://www.google.com"
).navigation(activity)
似乎如上,就是我们想要的效果。然而、然而、然而、:事与愿违,如此并不能配置extra=10010
,也就不能在Inteceptor
中根据postcard.extra
来判断了。
因为两个postcard
经过路由后,不是同一个对象了,最重要的是,其他值都还好,就是extra
这个标记值,代码修改的是不会传递给后面生成的postcard
的,而会被@Route(path="web",extra=10086)
中的extra
覆盖掉。这个可以看ARouter
源码,一步步debug
下去,就会知道在warehouse
的一个map
赋值RouteMeta
时候,覆盖的。有在github
上提交issues
,似乎看到有官方回复,暂时不会处理。所以有遇到这个问题的朋友,留心一下。
**另:**在ARouter
的跳转startActivityForResult
在Fragment
中调用,则在fragment
的onActivityResult
不会接收到回调。会被上层Activity
拦截掉。解决方案:
使用原生的context.startActivityForResult
调用(不是activity调用,否则也是一样,不能下发),需要注意如果Activity
覆写onActivityResult
内部需要调用super
才能下发。
如果用ARouter
调用的话,可以在Activity
中重写onActivityResult
并手动下发
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val fragments = supportFragmentManager.fragments
for (fragment in fragments) {
fragment.onActivityResult(requestCode,resultCode,data)
}
}
类似方法1,只是在模块化开发时,跨模块调用,出现不能引用到目的地Activity
的时候,来个半原生的方式跳转
//ARouter原生不支持fragment中的forResult,官方也不予以处理,这里变相的取到跳转目的地 的 class对象
val postcard = ARouter.getInstance().build(RouterPath.ROUTER_PATH_LOGIN_ACTIVITY)
LogisticsCenter.completion(postcard)//这不操作必不可少,完成postcard的参数赋值
startActivityForResult(Intent(context, postcard.destination), FRAGMENT_REQUEST_CODE_LOGIN)
后记: ARouter
还在逐步摸索使用中,慢慢学习,遇到后续问题,再做记录。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章