登录拦截的优雅实现

我们的目标就是做一个登录、收银台,将他们从业务中完全剥离出来,在不改变开发者原有的调用习惯的前提下,让登录、支付不添加任何具体的业务代码

背景

在日常开发中,经常会遇到各种跳转中夹杂登录的过程,进入登录页的各种操作,会将原本的流程拆的支离破碎,举几个例子

前提
A -> X,需要进行登录,或者 A 进行网络请求时 token 过期,则需要跳转登录 (这里的 X,是任意目标页面)

  1. 登录成功之后,要跳转到 X 页面
  2. 有时 A -> X 会传递参数, 登录成功之后要将参数带至 X
  3. 如果不登录,直接点返回,需要回到指定页面,也有可能回到 A 页面

以上内容按照正常逻辑应该如何实现,大概就是以下解决方案

  1. 传一个标记进去,告诉登录如果登录成功想要去哪
  2. 将要传递的参数传给登录,登录成功之后由登录代为传递到下一个页面(登录完全耦合到各个业务当中,登录里面要写很多跳转传值逻辑)
  3. 不登录直接返回则不好处理了,只能传过去要返回到页面
  4. 终极大招: 登录成功之后,统一回到登录触发页,继续之前的流程(这样会一闪而过,不丝滑,产品不接受)

以上到解决方案都或多或少的存在一些问题,根本的问题还是和登录的耦合性太高,未来的支付也会存在这个问题.我相信很多公司的处理方式就是目前的模式,导致登录、支付打开一堆的业务嵌套、耦合,以至于没有人敢动.

我们的目标就是做一个登录、收银台,将他们从业务中完全剥离出来,在不改变开发者原有的调用习惯的前提下,让登录、支付不添加任何具体的业务代码

我们以登录为例,主要讲思想,明白了思想,任何业务都一样

解决方案

我这里所说的有一些前提

  1. 是基于 Activity 为页面承载的处理,如果你的项目全是 Fragment 实现,则需要你根据项目实际情况进行修改,反正思路是一样的
  2. 项目架构是非组件化架构,如果是组件化的,则直接使用路由自带的拦截器,思路和本篇设计思路一样,可以参考 ARouter

本来我的想法是写一个登录拦截器, Java 可以通过工具类的方式, Kotlin 可以通过给 Activity 添加拓展函数的方式

但是以上都会改变开发者原有的调用习惯,不能通过 startActivity() 进行跳转了

所以我决定对 startActivity() 的源码进行修改,这时候,需要你有一个 BaseActivity 了

这里提供两个思路

  1. 无论上个页面传递多少参数,都保存在 bundle 当中,只要将上个页面的 bundle 保存下来,并将目标页面也存入 bundle,一并交给登录页面处理
  2. 之间修改当前 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 的 startActivity() 是调用的 Fragment 中的 startActivity(),而不是 Activity 中的 startActivity()

所以说如果在 Fragment 也想走拦截器,就只能调用他所依附的 Activity 的 startActivity(),比如:


            (context as MainActivity)
            .startActivity(Intent(context, SettingActivity::class.java)
            .putExtra(KeyUtils.VALUE, "哈哈哈"))
            

调用他所依附的 Activity 的 startActivity() 目前来说还不知道会存在什么问题

个人验证暂时没有问题,如果有人知道还请指出,如果有人有更好的解决方案还请分享,谢谢.

系列文章

到此,拦截的核心就已经完成了,接下来需要处理的是一些细节问题

我会在接下来的文章当中,分别处理:

  1. 登录拦截的优雅实现
  2. 绿色通道问题
  3. 不登录直接返回跳转目标页面问题
  4. 跳转传值回传问题
  5. 以及一些暂未发现,后续发现或者读者提出的新问题补充进此列表

微信扫描二维码,关注我的公众号
关注这个公众号,我们聊聊别的,一起搞钱。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值