登录拦截的优雅实现
我们的目标就是做一个登录、收银台,将他们从业务中完全剥离出来,在不改变开发者原有的调用习惯的前提下,让登录、支付不添加任何具体的业务代码
背景
在日常开发中,经常会遇到各种跳转中夹杂登录的过程,进入登录页的各种操作,会将原本的流程拆的支离破碎,举几个例子
前提
A -> X,需要进行登录,或者 A 进行网络请求时 token 过期,则需要跳转登录 (这里的 X,是任意目标页面)
- 登录成功之后,要跳转到 X 页面
- 有时 A -> X 会传递参数, 登录成功之后要将参数带至 X
- 如果不登录,直接点返回,需要回到指定页面,也有可能回到 A 页面
以上内容按照正常逻辑应该如何实现,大概就是以下解决方案
- 传一个标记进去,告诉登录如果登录成功想要去哪
- 将要传递的参数传给登录,登录成功之后由登录代为传递到下一个页面(登录完全耦合到各个业务当中,登录里面要写很多跳转传值逻辑)
- 不登录直接返回则不好处理了,只能传过去要返回到页面
- 终极大招: 登录成功之后,统一回到登录触发页,继续之前的流程(这样会一闪而过,不丝滑,产品不接受)
以上到解决方案都或多或少的存在一些问题,根本的问题还是和登录的耦合性太高,未来的支付也会存在这个问题.我相信很多公司的处理方式就是目前的模式,导致登录、支付打开一堆的业务嵌套、耦合,以至于没有人敢动.
我们的目标就是做一个登录、收银台,将他们从业务中完全剥离出来,在不改变开发者原有的调用习惯的前提下,让登录、支付不添加任何具体的业务代码
我们以登录为例,主要讲思想,明白了思想,任何业务都一样
解决方案
我这里所说的有一些前提
- 是基于 Activity 为页面承载的处理,如果你的项目全是 Fragment 实现,则需要你根据项目实际情况进行修改,反正思路是一样的
- 项目架构是非组件化架构,如果是组件化的,则直接使用路由自带的拦截器,思路和本篇设计思路一样,可以参考 ARouter
本来我的想法是写一个登录拦截器, Java 可以通过工具类的方式, Kotlin 可以通过给 Activity 添加拓展函数的方式
但是以上都会改变开发者原有的调用习惯,不能通过 startActivity() 进行跳转了
所以我决定对 startActivity() 的源码进行修改,这时候,需要你有一个 BaseActivity 了
这里提供两个思路
- 无论上个页面传递多少参数,都保存在 bundle 当中,只要将上个页面的 bundle 保存下来,并将目标页面也存入 bundle,一并交给登录页面处理
- 之间修改当前 Intent 的目标页面,在进入登录页和目标页,一直使用同一个 Intent。
这里采用第二个思路
说是修改 startActivity() 的源码,其实就是对 Intent 的参数值进行修改
原理就一句话 通过改变 Intent 的目标页面来实现跳转流程的改道
说到这里聪明的人应该会理解我的意思了,虽然会有很多的细节需要完善,但是最最最核心的就是修改 Intent 的目标地址了
如果没有登录,除了修改目标地址,再将目标页面跳转页面当作 Intent 参数保存进 Intent
这样,一个最简单、最基础、最核心的登录拦截跳转就完成了
所以,我们在 BaseActivity 的 startActivity() 中做修改如下:
override fun startActivity(intent: Intent?) {super.startActivity(if (isLogin()) {intent} else {intent?.putExtra(KeyUtils.TARGET_ACTIVITY, intent.component?.className)?.setClass(this, LoginActivity::class.java)})}
然后在登录的成功回调中,进行处理
private val targetActivity by lazy {Class.forName(intent.extras?.getString(KeyUtils.TARGET_ACTIVITY)!!)}private fun loginSuccess() {if (targetActivity.isNotEmptyObj()) {startActivity(intent.setClass(this, targetActivity))}}
然后在目标页面正常取值就行了
可以看出,以上并没有改变开发者的开发习惯,该怎么跳转传值就怎么写
在上面的公众号中回复 登录拦截 查看有代码实现的完整文章
后记
但是有一个遗憾的点:在 Fragment 中调用 startActivity() 时候并不会走我们封装的拦截器,因为:
所以说如果在 Fragment 也想走拦截器,就只能调用他所依附的 Activity 的 startActivity(),比如:
(context as MainActivity).startActivity(Intent(context, SettingActivity::class.java).putExtra(KeyUtils.VALUE, "哈哈哈"))
调用他所依附的 Activity 的 startActivity() 目前来说还不知道会存在什么问题
个人验证暂时没有问题,如果有人知道还请指出,如果有人有更好的解决方案还请分享,谢谢.
系列文章
到此,拦截的核心就已经完成了,接下来需要处理的是一些细节问题
我会在接下来的文章当中,分别处理:
- 登录拦截的优雅实现
- 绿色通道问题
- 不登录直接返回跳转目标页面问题
- 跳转传值回传问题
- 以及一些暂未发现,后续发现或者读者提出的新问题补充进此列表
关注这个公众号,我们聊聊别的,一起搞钱。
标签:
相关文章
-
无相关信息