Android彻底组件化—如何使用Arouter

本文介绍如何在Android组件化方案中使用ARouter进行UI跳转,并实现代码和资源隔离,确保组件间自由且可控地跳转。文章涵盖配置、自定义类型传递、拦截器实现及生命周期控制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

得到Android组件化方案已经开源,参见Android组件化方案开源。方案的解读文章是一个小的系列,这是系列的第五篇文章:

  1. Android彻底组件化方案实践
  2. Android彻底组件化demo发布
  3. Android彻底组件化-代码和资源隔离
  4. Android彻底组件化—UI跳转升级改造
  5. Android彻底组件化—如何使用Arouter

上篇文章讲到,AndroidComponent已经进行了UI跳转的升级改造,可以支持路由的自动注册和路由表的自动生成。但是很多使用组件化方案的同学都表示项目中已经接入ARouter来进行UI跳转,迁移成本比较高。因此我就专门写了这篇文章,讲解一下如何在组件中使用ARouter。

不论用DDComponent自带的方案还是ARouter,要做到组件之间自由并且可控的跳转,需要做到下面几点:

1、路由跳转需要支持传递基本类型和自定义类型(例如Object) 2、路由的跳转需要和组件的生命周期一致,即只有加载的组件才可以跳转,卸载后的组件是不可达的 3、最好生成路由表,组件对外提供的路由可以轻松查阅到

下面我们就从配置开始一步步的讲怎么使用ARouter

增加必要的配置

basiclib模块中增加以下依赖,basiclib是组件化框架中共用的依赖库:

compile 'com.alibaba:arouter-api:1.3.0'
复制代码

在跳转的目标组件的build.gradle中,增加以下配置:

android {
    defaultConfig {
	...
	javaCompileOptions {
	    annotationProcessorOptions {
		arguments = [ moduleName : project.getName() ]
	    }
	}
    }
}
dependencies {
    annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
    ...
}
复制代码

在组件化框架中,我们的示例是从readercomponent跳转到sharecomponent,所以上述配置增加在sharecomponent下面的build.gradle中。

在目标页面增加相应的注解

我们以“分享图书” 页面为例

@Route(path = "/share/shareBook")
public class ShareActivity extends AppCompatActivity {
复制代码

在进入这个页面,需要传入两个参数,一个是String类型的bookName,一个是自定义类型Author的author

@Autowired
String bookName;
@Autowired
Author author;
复制代码

如何传递自定义类型

由于自定义类型Author需要跨组件传递,我们知道,DDComponent的核心之处就是在组件之间见了一堵墙,在编译期代码和资源都是完全隔离的,所以Author必须定义在share组件向外提供的服务中。所以我们在component中,定义Author类:

public class Author {
    private String name;
    private int age;
    private String county;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getCounty() {
        return county;
    }
    public void setCounty(String county) {
        this.county = county;
    }
}
复制代码

现在就解决了Author的可见性问题,但是为了能在路由中传递,按照ARouter的要求,还需要自己实现SerializationService:

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {
    @Override
    public void init(Context context) {}
    @Override
    public <t> T json2Object(String text, Class<t> clazz) {
        return JSON.parseObject(text, clazz);
    }
    @Override
    public String object2Json(Object instance) {
        return JSON.toJSONString(instance);
    }
    @Override
    public <t> T parseObject(String input, Type clazz) {
        return JSON.parseObject(input, clazz);
    }
}
复制代码

这里笔者就遇到了一个坑,本来我把这个类定义在readercomponent中,结果运行之后会报空指针异常。只有我把类移到sharecomponent之后,异常才消失。暂时没找到原因,但是定义在这里,加入要跳转到readercomponent怎么办呢?

发起跳转

在组件化框架demo中,发起跳转是readercomponent中的ReaderFragment中,demo中列出了两个示例: 普通跳转

private void goToShareActivityNormal() {
    Author author = new Author();
    author.setName("Margaret Mitchell");
    author.setCounty("USA");
    ARouter.getInstance().build("/share/shareBook")
            .withString("bookName", "Gone with the Wind")
            .withObject("author", author)
            .navigation();
}
复制代码

以及startActivityForResult

private void goToShareActivityForResult() {
    Author author = new Author();
    author.setName("Margaret Mitchell");
    author.setCounty("USA");
    ARouter.getInstance().build("/share/shareMagazine")
            .withString("bookName", "Gone with the Wind")
            .withObject("author", author)
            .navigation(getActivity(), REQUEST_CODE);
}
复制代码

控制生命周期

经过上面的操作,已经可以完成UI跳转了。但是如果运行demo就可以发现,此时即使卸载了分享组件,分享书的页面还是可以进入的,说明生命周期没有同步。在DDComponent自带的方案中是不存在这个问题的,因为跳转的逻辑已经与组件化生命周期绑定在一起。 这里就用到ARouter自带的拦截器功能,每个组件都需要定义一个拦截器,当组件卸载之后需要拦截住该组件的跳转入口。 下面是分享组件拦截器的示例代码:

@Interceptor(priority = 1, name = "分享组件拦截器")
public class ShareInterceptor implements IInterceptor {
    public static boolean isRegister;
    Context mContext;
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if (isRegister) {
            callback.onContinue(postcard);
        } else if ("/share/shareBook".equals(postcard.getPath())
                || "/share/shareMagazine".equals(postcard.getPath())) {
            MainLooper.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(mContext, "分享组件已经卸载", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    @Override
    public void init(Context context) {
        mContext = context;
    }
}
复制代码

这里通过一个isRegister开关来控制拦截器是否生效,为了保证生命周期一致性,在ShareApplike中增加赋值逻辑:

public class ShareApplike implements IApplicationLike {
    @Override
    public void onCreate() {
        ShareInterceptor.isRegister = true;
    }
    @Override
    public void onStop() {
        ShareInterceptor.isRegister = false;
    }
}
复制代码

但是这里也遇到了两个小坑,不知道是否是ARouter使用不当: (1)添加或者修改拦截器之后,必须卸载重装app才能生效,不论是clean还是rebuild都是不生效的 (2)拦截器中需要硬编码该组件的所有路由,例如/share/shareBook等,一旦路由发生了改变,一定要记得修改这个地方

路由表生成

这个ARouter暂时没有提供,DDComponent自带的方案增加了这个功能,当组件build生成之后,在根目录生成UIRouterTable文件夹,里面会列出每个组件向外提供的路由表以及具体参数

auto generated, do not change !!!! 

HOST : share

分享杂志页面
/shareMagazine
author:com.luojilab.componentservice.share.bean.Author
bookName:String

分享书籍页面
/shareBook
author:com.luojilab.componentservice.share.bean.Author
bookName:String
复制代码

这点对于组件的协同开发是比较重要的,毕竟跳转之前翻阅别人的代码是件比较费事的工作

简单做一个总结:

  1. ARouter是一个优秀的路由跳转方案,DDComponent自带的方案也参考了很多其中的想法,功能很强大
  2. 使用中需要与组件化方案兼容的地方主要是生命周期相关,在拦截器上增加部分逻辑就可以完成
  3. ARouter使用中还存在一些小的问题,可能是姿势不对,接入中走了不少弯路,有熟悉这块的朋友可以指出原因
  4. 路由表没有自动生成,对外没有暴露有哪些路由协议和参数,对于组件之间协同开发不太友好

上面的代码已经发布DDComponent的master-arouter分支,欢迎大家使用,源码地址: github.com/mqzhangw/An…

<think>好的,我现在要回答用户关于Android组件化和模块化区别的问题。首先,我得确保自己正确理解这两个概念,然后组织一个清晰易懂的解释。 首先,模块化。我记得模块化通常是指将应用拆分成多个功能模块,每个模块负责特定的功能,比如登录模块、支付模块等。模块化的目的是提高代码的复用性和可维护性,各个模块之间可能通过接口进行通信,但可能存在一定的耦合。 然后是组件化组件化听起来更强调独立性,每个组件可以单独开发、测试,甚至作为独立的APK运行。组件之间应该低耦合,可能使用路由或消息总线来通信。组件化的目标可能是更灵活地组合应用,方便团队协作和功能复用。 不过,我可能有些混淆,要进一步确认两者的区别。例如,模块化是否更多是代码层面的拆分,而组件化更偏向业务层面的独立?或者是否有其他关键差异,比如依赖管理、构建方式的不同? 另外,用户可能想知道实际应用场景,比如什么时候用模块化,什么时候用组件化要举例说明,比如模块化可能用于同一项目内的功能划分,而组件化适用于跨项目的共享组件。 还要注意技术实现上的不同,比如组件化可能使用动态加载、路由框架,而模块化可能更多使用Gradle子模块。可能还要提到两者的共同点,比如都为了提高代码维护和团队协作。 最后,要确保回答结构清晰,分点说明两者的定义、核心目标、技术差异、适用场景等。避免使用专业术语过多,用简单的中文解释,帮助用户逐步理解。</think>Android组件化与模块化的区别主要体现在设计目标和实现方式上。以下是逐步对比: ### 一、定义与核心目标 1. **模块化(Modularization)** - **定义**:将应用按**功能**拆分为多个独立模块(例如登录模块、支付模块)。 - **目标**:提高代码复用性、降低耦合,便于团队协作开发。 - **示例**: $$ \text{APP} = \text{模块A} + \text{模块B} + \text{模块C} $$ 每个模块通过接口调用其他模块功能。 2. **组件化(Componentization)** - **定义**:将应用按**业务能力**拆分为独立组件(例如用户中心组件、商品详情组件)。 - **目标**:实现组件**独立运行与复用**,支持动态替换或组合。 - **示例**: $$ \text{APP} = \sum_{i=1}^{n} \text{组件}_i $$ 每个组件可单独编译为APK。 --- ### 二、技术差异对比 | **对比维度** | **模块化** | **组件化** | |--------------------|---------------------------------------|---------------------------------------| | **通信方式** | 通过接口直接调用 | 依赖路由框架(如ARouter)或事件总线 | | **依赖关系** | 模块间可能存在双向依赖 | 组件间完全解耦,仅依赖基础库 | | **编译方式** | 作为Library模块集成到主工程 | 可独立编译运行(通过Gradle配置切换) | | **业务独立性** | 功能复用为主 | 支持跨项目复用,甚至作为SDK提供 | --- ### 三、典型应用场景 1. **模块化适用场景** - 同一项目内功能划分(例如电商App拆分商品、订单模块) - 要减少编译时间的单体应用 2. **组件化适用场景** - 跨团队协作开发(每个团队负责独立组件) - 要动态下发功能的场景(如插件化) - 多App共享通用业务(例如多个App共用登录组件) --- ### 四、演进关系 组件化可视为模块化的**高阶形态**: 1. 先通过模块化解耦功能 2. 再通过组件化实现彻底独立 --- ### 五、技术实现关键点 1. **模块化** - 使用Gradle的`implementation`管理依赖 - 通过接口隔离模块(如`LoginService`接口) 2. **组件化** - 定义路由表(如`Router.register("/user/detail", UserActivity::class)`) - 使用`build.gradle`动态切换`application`与`library`模式 ```groovy if (isComponentMode) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } ``` --- ### 六、总结 | **维度** | **模块化** | **组件化** | |--------------|--------------------------|---------------------------| | **核心思想** | 功能拆分 | 业务自治 | | **耦合度** | 中等 | 低 | | **复用层级** | 项目内复用 | 跨项目复用 | | **复杂度** | 较低 | 较高(解决通信/依赖) | 选择建议: - 小型项目优先模块化 - 大型项目或跨团队协作推荐组件化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值