`

ARouter 拦截器之多 module 独立运行

阅读更多

本文已首发微信公众号「code小生」,大家可以搜索关注,专注安卓技术分享。

本文说明

上篇文章已分享了路由配置、跳转、原理、完整的效果演示gif以及源码,而且是多 module 项目演示的,算是路由 ARouter 的入门,还没配置使用的可以先去看看。

本文的内容主要涉及如下两个:

  • 路由拦截器使用
  • module 独立运行

前者在我们开发中有这样一种应用场景,默认用户不登录可以浏览一部分页面,当点击部分页面的时候就需要先去登录,也就是跳转到登录页面,普通的做法是根据需求挨个去做点击事件,这就很麻烦,如果需要跳转登录的时候传递参数啥的,那就改动超级大了;而路由ARouter的拦截器功能就很好的解决了这个问题,还支持自定义拦截器,使用起来很灵活。

后者的使用场景适合项目大,多人开发的情景,这样可以各自负责一个模块,独立调试运行,利于项目管理以及代码的维护。这块在上一篇文章的前提下还需要额外配置,本文会讲。

module 独立运行

先来看看module独立运行,然后我们在各个模块做一个模拟的跳转页面需要验证登录的示例,这样比较清晰。

第一步:配置 gradle.properties

gradle.properties 文件中添加如下代码

#是否需要单独运行某个模块 true:表示某个模块不作为依赖库使用
isSingleCircleModule=true
#isSingleCircleModule=false
isSingleHomeModule=true
#isSingleHomeModule=false

第二步:配置app下的build.gradle

在app下的build.gradle文件配置

if (!isSingleCircleModule.toBoolean()) {
    implementation project(path: ':circle')
}
if (!isSingleHomeModule.toBoolean()){
    implementation project(path: ':home')
}

并注释掉原来的依赖

//    implementation project(path: ':circle')
//    implementation project(path: ':home')

第三步:配置各独立模块下的build.gradle

circle模块下build.gradle文件最顶部改动如下:

//plugins {
//    id 'com.android.library'
//}

if (isSingleCircleModule.toBoolean()) {
    apply plugin: 'com.android.application'else {
    apply plugin: 'com.android.library'
}

home模块下build.gradle文件最顶部改动如下:

//plugins {
//    id 'com.android.library'
//}

if (isSingleHomeModule.toBoolean()) {
    apply plugin: 'com.android.application'else {
    apply plugin: 'com.android.library'
}

第四步:看效果

上面的配置完成后,点击Sync Project with Gradle Files 等待编译完成,可看到如下状态:

Select Run弹窗Select Run弹窗

这个时候我们选择其中一个module运行,会发现报错如下:

Could not identify launch activity: Default Activity not found
Error while Launching activity

很明显,我们都知道Android程序的主入口是从清单文件配置的,但我们的各module都还没有做这个工作。

circle模块下的清单文件中,配置如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gs.circle">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/app_icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".CircleActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

其中的iconlabel以及theme都可以定义在baselib中,这样我们任何 module 配置的时候就可以直接引用,而无需各自复制一份了;除此之外,values文件夹下的东西都可以移动到baselib下,方便其他模块引用,这也就是baselib模块的作用,如果你要细分,还可以j将公共资源放在一个独立的模块里,这个模块通常叫做:commonlib,具体情况而定。

配置完清单文件,运行后发现桌面会多出来一个 APP icon,打开只有一个页面,就是我们的circlemodule的主页面。home模块的清单配置就不展示了,下面看下效果:

module独立运行module独立运行

这个时候再切回去运行app模块,如果发现有问题,先卸载再运行就ok了。但是会有一个问题,原来可以跳转其他模块的功能,现在跳转不了了,这其实很正常,因为在组件化开发模式下,每个 module 都是独立的app,所以肯定不能直接跳转过去。

那如何实现正常跳转呢?

需要两步,将gradle.properties中的代码修改为如下:

#isSingleCircleModule=true
isSingleCircleModule=false
#isSingleHomeModule=true
isSingleHomeModule=false

接着将circlehome模块的清单文件中的 application属性和默认启动配置项删掉,然后再运行就 ok 了。

如果想将其中一个作为依赖库使用,那么就指匠情挑设置为false即可。

关于组件之间 AndroidManifest 合并问题

其实这个可以在正式打包的时候,注释掉module中的相关代码即可,毕竟是在组件模式。那有没有办法解决每次都要注释的问题呢?答案是yes.

大致思路如下:

在可独立运行的module的res->main文件夹下新建一个文件夹(命名自定义),然后将对应的清单文件复制一份,名称不需要修改,内容的差别就是前面提到的,去掉application属性和默认启动配置项。
接着在对应 module 的 build.gradle 中指定表单的路径,代码如下:

sourceSets {
    main {
        if (isSingleCircleModule.toBoolean()) {
            manifest.srcFile 'src/main/module/AndroidManifest.xml'
        } else {
            manifest.srcFile 'src/main/AndroidManifest.xml'
        }
    }
}

这样在不同的开发模式下就会读取到不同的 AndroidManifest.xml ,然后我们需要修改这两个表单的内容以为我们不同的开发模式服务。

单模块独立运行小结

优点:

  • 项目耦合度低,开发效率高,出现问题易排查
  • 利于项目进度管理,分工明确
  • 适合多人大项目

缺点:

  • 前期配置比较复杂,开发过程中需要修改部分配置
  • 稳定性不好把握,毕竟不是google官方出的框架,后期出问题不好处理

其实还有很多问题,实践过的应该明白,每个项目都有自己的独特之处,会有各种各样的奇怪问题,但一般网上我们都可以找到解决方案。

路由拦截器使用

首先还是需要添加几个配置,在工程下的build.gradle文件中添加下面这行代码:

classpath 'com.alibaba:arouter-register:1.0.2'

app模块的build.gradle文件下,配置改动如下:

plugins {
    id 'com.android.application'
    id 'com.alibaba.arouter' // 拦截器必须配置
}

配置完这两步,按照惯例,该是编译了。

为了演示,我这里在app下新建一个名为LoginActivity的页面,作业登录拦截后跳转的页面,页面内容只有一个提示文本,这里补贴代码。

然后分别在宿主模块app、功能模块circlehome中去做跳转登录页面,看看我们的拦截器是否起到了拦截作用,下面开始定义拦截器。

要独立运行某个模块,这里就不再赘述了,大家自行修改配置即可。

拦截器完整代码如下:

/**
 * Description: 登录拦截器
 * Date: 2021/10/9 10:42
 * <p>
 * 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
 * * <p>
 * * priority 数值越小权限越高
 */
@Interceptor(priority = 2, name = "登录ARouter拦截器")
public class LoginInterceptor implements IInterceptor {

    private Context mContext;

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        boolean isLogin = mContext.getSharedPreferences("arouterdata", mContext.MODE_PRIVATE).getBoolean("isLogin"false);
        if (isLogin) {
            callback.onContinue(postcard);
        } else {
            switch (postcard.getPath()) {
                // 需要登录的拦截下来
                case ARouterPath.APP_MY_INFO:
                    ARouter.getInstance().build(ARouterPath.LOGIN_PAGE).with(postcard.getExtras()).navigation();
                    break;
                default:
                    callback.onContinue(postcard);
                    break;
            }
        }
    }

    /**
     * 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
     *
     * @param context
     */
    @Override
    public void init(Context context) {
        mContext = context;
    }

}

拦截器初始化需要重新安装才会生效,这点要注意。拦截器是不需要我们手动显示调用的,而是框架通过注解来使用的,所以我们只需要写好逻辑代码即可。

以上代码可以实现模块内和跨模块跳转拦截,本地的登录状态我这里没有处理逻辑,所以每次都会被拦截到。下面看效果:

拦截器效果拦截器效果

演示效果模拟进入MyInfoActivity页面时需要先登录,分别从三个模块做了跳转演示。

总结

组件化module独立运行与合并操作起来相对繁琐一点,但优点也很明显。路由框架ARouter的拦截器使用起来就很简单了,其实拦截器完全可以在学完上一篇之后,直接使用,如果组件化多模块独立运行实际项目使用不到,可以先跳过,简单了解流程即可。

Android的框架演变也很快,“三化技术”在两年前特别火,几乎大家都在讨论,但并没有持续多长时间就被新出的技术替代了,而作为一个开发者,自己需要掌握一个基本技能:从零开始搭建一个项目框架,并且这个框架尽可能的要跟上项目的持续发展

本文全部代码已打包:关注微信公众号code小生回复arouter

分享到:
评论

相关推荐

    Android-基于Arouter的登录拦截

    在Android应用开发中,用户权限管理和登录拦截是一个重要的部分,特别是在多模块化、组件化的大型项目中。Arouter是一款优秀的Android路由框架,它提供了一种高效、灵活的方式来管理应用程序内部的跳转。在这个主题...

    ARouter路由实现拦截跳转

    ARouter提供拦截器机制,用于在路由跳转前进行一些额外的操作,比如权限检查、登录状态验证等。创建一个自定义的Interceptor类,继承`com.alibaba.android.arouter.core.Interceptor`,并在其中实现`intercept...

    WebService之自定义拦截器(server+client)

    在IT行业中,Web服务是应用程序之间进行通信的一种标准方法,而WebService之自定义拦截器的实现,无论是对于服务器端还是客户端,都是为了增强服务的功能性和安全性。本文将深入探讨自定义拦截器的概念、作用以及...

    mybatis 分页拦截器及拦截器配置

    MyBatis 分页拦截器是实现数据库查询分页效果的一种高效解决方案。在传统的SQL查询中,我们通常需要手动编写分页语句,但这容易出错且不易维护。通过使用分页拦截器,我们可以将分页逻辑封装起来,使得在编写Mapper...

    请求拦截器和响应拦截器.docx

    请求拦截器和响应拦截器 请求拦截器和响应拦截器是 Axios 库中提供的一种机制,用于在发送请求之前和响应数据返回之前对数据进行处理。下面是对这两个概念的详细解释: 请求拦截器 请求拦截器是指在发送请求之前...

    CXF3.0+Spring3.2 自定义拦截器

    4. **拦截器链**:CXF允许你定义多个拦截器,形成一个处理链。当请求或响应通过这个链时,每个拦截器都有机会处理消息。如果某个拦截器抛出异常,链会被中断。 5. **自定义逻辑**:在自定义拦截器的`handleMessage`...

    自定义拦截器的实现以及拦截器的详细配置

    -- 可以添加更多的拦截器,按执行顺序排列 --&gt; &lt;!-- 配置Action,指定使用拦截器栈 --&gt; &lt;result&gt;success.jsp ``` 3. **注解方式配置**:除了XML配置,Struts2还支持注解方式来配置拦截器。在Action类上...

    Struts2拦截器及其用法详细说明

    - XML配置:在`struts.xml`文件中,使用`&lt;interceptor&gt;`元素定义拦截器,`&lt;interceptor-stack&gt;`元素组合多个拦截器,`&lt;package&gt;`元素下的`interceptors`属性指定拦截器栈。 ```xml &lt;!-- 可以添加其他内置或...

    uni-app 请求拦截器

    【uni-app请求拦截器】是基于uni-app框架实现的一种机制,它允许开发者在发送网络请求前和接收到响应后执行自定义的操作。这种机制对于统一处理请求头、数据格式、错误处理以及添加全局的请求前后的逻辑非常有用,极...

    拦截器和过滤器的区别

    - **独立性较高**:拦截器并不依赖于Servlet容器,因此可以在任何环境中使用拦截器技术来实现类似的功能。 - **适用范围广**:除了传统的Web应用外,拦截器还可以应用于各种基于Java的框架或库中。 - **过滤器**...

    360弹窗拦截器 v6独立版-流氓软件弹窗广告拦截神器.zip

    360弹窗拦截器独立版是从最新的360安全卫士中提取的弹窗拦截工具,不占资源,功能全面,独立运行。360弹窗拦截器可以拦截各种应用内置的广告弹窗,效果不错,很实用的日常必备小工具。 使用方法 首先保证你的...

    微信小程序请求拦截器 ,响应拦截器

    微信小程序请求拦截器 ,响应拦截器,结合微信小程序二次封装request 一起使用

    Spring Cloud OpenFeign - - - >拦截器

    初学者很容易将 Spring MVC 拦截器 和 Spring Cloud OpenFeign 拦截器搞混,误以为OpenFeign拦截器就是SpringMVC拦截器:Spring MVC拦截器发生在客户端 和 服务端之间,在客户端向服务端发送请求时进行拦截处理。...

    springMVC拦截器项目

    为了保持代码的清晰和模块化,通常建议将不同的拦截逻辑(如权限控制、日志记录)分别封装在独立的拦截器类中。这样可以提高代码的复用性和可维护性。 通过这个项目,你可以学习到 SpringMVC 框架的核心概念,以及...

    理解拦截器用于在某个方法或字段被访

    拦截器链是由多个拦截器组成,按照特定的顺序依次执行。每个拦截器都有"before"和"after"两个阶段,即在目标方法执行前和执行后执行的逻辑。如果在"before"阶段的某一个拦截器阻止了请求的继续,那么目标方法将不会...

    MyBatis拦截器:给参数对象属性赋值的实例

    如果操作类型是这两种之一,拦截器就会继续进行属性赋值。否则,它会跳出循环,不进行额外操作。 在实际赋值部分,由于示例代码没有给出具体的赋值逻辑,通常这会涉及到反射(`java.lang.reflect.InvocationTarget...

    mybatis拦截器实现通用权限字段添加的方法

    MyBatis拦截器实现通用权限字段添加的方法 MyBatis拦截器是一种非常实用的技术,可以用来实现各种复杂的数据库操作。本文将详细介绍如何使用MyBatis拦截器来实现通用权限字段添加,达到灵活、可靠、可维护的数据库...

    SpringBoot拦截器原理解析及使用方法

    在SpringBoot框架中,拦截器是一个非常重要的组件,它能够在请求到达控制器(Controller)之前或者之后对请求进行拦截,以完成一些预处理或后处理操作。拦截器通常用于权限检查、日志记录、性能监控等场景。 拦截器...

    struts2 拦截器

    2. **拦截器链**:在Struts2中,多个拦截器可以形成一个拦截器链,每个拦截器按照定义的顺序依次执行。如果所有拦截器都允许Action执行,那么Action的结果将被传递到下一个拦截器,直到整个链执行完毕。 ### 二、...

Global site tag (gtag.js) - Google Analytics