组件化开发步骤

【Android之组件化开发】

前言

说起组件化,就不得不提一下模块化和插件化。它们的概念十分相似,咋一看还真分不清它们的区别是什么,很多人都会将它们搞混。严格意义来说,组件化、插件化其实也算是模块化的观念。

下面,我们先这三个xx化有个基本的了解。

模块化

在Android studio中,相信大家都创建过Module,而一个Module就是一个小的项目,而每一个Module也被称为模块。

因此,在项目中,我们可能会设计common模块, common_business模块、db模块等等。

设计这些模块的好处是什么?

相比于包来讲,模块更灵活,耦合更低,随意插拔,想引入哪个就引入哪个。

根据不同的关注点,

将一个项目的公共的部分抽取出来,形成独立的Module,就是模块化。当然,模块化不只包含公共部分,当然也可以是业务模块。

组件化

组件化,它是建立在模块化思想上的一次演进,一个变种。

我们知道,Module又可以是两种格式:

  • application:当Module是application的时候,它将具备独立运行的能力
  • library:当Module是library的时候,它将作为整个App的一个模块,与App一同运行

组件化的核心是模块角色的可转换性:在打包时, 是library;在调试时, 是application。

调试时,使模块作为一个单独的app,你需要关注的业务更专一,并且相对来说编译速度也会更快。

插件化

将一个完整的工程,按业务划分为不同的插件,这也是分治法的一种体现。

组件化的单位是组件(module),而插件化的单位是apk。插件化还可以实现热插拔(热更新)。

组件化的灵活性在于按加载时机切换,而插件化的灵活性在于加载apk,完全可以动态下载,动态更新,比组件化更灵活。

插件化本质上就是不同的apk, 你把各种不同的模块单独做成一个完全独立的app,需要整合的时候就插在一起,就形成了一个大型的app了。

插件化的加载是动态的,这点很重要,也是灵活的根源。

通信方式

  • 模块化的通信方式,无非是相互引入;我抽取了common,其他模块使用自然要引入这个module。
  • 组件化的通信方式,按理说可以划分为多种,主流的是隐式和路由。隐式的存在使解耦与灵活大大降低,因此路由是主流。
  • 插件化的通信方式,不同插件本身就是不同的进程了。因此通信方式偏向于Binder机制类似的进程间通信。

本篇的重点是介绍组件化,因此模块化和插件化就不再赘述,我们重点讲讲组件化。

组件化的使用

组件化就是将一个app分成多个Module,每个Module都是一个组件(也可以是一个基础库供组件依赖),开发的过程中我们可以单独调试部分组件,组件间不需要互相依赖,但可以相互调用,最终发布的时候所有组件以lib的形式被主app工程依赖并打包成1个apk。
集成至Android步骤如下:

1、在工程根目录的build.gradle中添加cc-register插件的classpath。最新版本号1.1.2

dependencies {
    classpath 'com.android.tools.build:gradle:3.6.3'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath 'com.billy.android:cc-register:1.1.2'   
}

2、在工程根目录创建一个名为"cc-settings-2.gradle"的文件,并将以下代码复制到该文件中(也可直接下载github中的cc-settings-2.gradle文件到工程根目录)

project.apply plugin: 'cc-register'
project.dependencies.add('api', "com.billy.android:cc:2.1.6") //用最新版

3、在主app module中添加对cc-settings-2.gradle文件的依赖将apply plugin: 'com.android.application’替换为

ext.mainApp = true //标记为主app 
apply from: rootProject.file('cc-settings-2.gradle')

如图所示:
在这里插入图片描述

4、新建一个module,并在该module下的build.gradle中添加对cc-settings-2.gradle文件的依赖,同时,将applicationId去除或者修改,与步骤3类似

apply from: rootProject.file('cc-settings-2.gradle')

在这里插入图片描述

5、在主app module中按如下方式添加对组件module的依赖

在这里插入图片描述

6、创建组件类,向外暴露当前组件提供的服务,新建一个类实现IComponent接口即可

public class ComponentA implements IComponent {
    @Override
    public String getName() {
        //指定组件的名称
        return "ComponentA";
    }
    @Override
    public boolean onCall(CC cc) {
        String actionName = cc.getActionName();
        switch (actionName) {
            case "showActivity": //响应actionName为"showActivity"的组件调用
                //跳转到页面:ActivityA
                CCUtil.navigateTo(cc, MainActivityx.class);
                //返回处理结果给调用方
                CC.sendCCResult(cc.getCallId(), CCResult.success());
                //同步方式实现(在return之前听过CC.sendCCResult()返回组件调用结果),return false
                return false;

            case "showActivity2": //响应actionName为"showActivity"的组件调用
                //跳转到页面:ActivityA
                CCUtil.navigateTo(cc, Main2Activity.class);
                //返回处理结果给调用方
                CC.sendCCResult(cc.getCallId(), CCResult.success());
                //同步方式实现(在return之前听过CC.sendCCResult()返回组件调用结果),return false
                return false;

            default:
                //其它actionName当前组件暂时不能响应,可以通过如下方式返回状态码为-12的CCResult给调用方
                CC.sendCCResult(cc.getCallId(), CCResult.errorUnsupportedActionName());
                return false;
        }
    }
}

7、调用组件

调用组件分为同步调用和异步调用2种方式
同步调用:调用方将用同步的方式获得返回的调用结果
异步调用:调用方通过回调接收组件的调用结果

//同步调用,直接返回结果
val result = CC.obtainBuilder("ComponentA")
    .setActionName("showActivity")
    .build()
    .call()

//或 异步调用,不需要回调结果
val callId = CC.obtainBuilder("ComponentA")
    .setActionName("showActivity")
    .build()
    .callAsync()

//或 异步调用,在子线程执行回调
val callId = CC.obtainBuilder("ComponentA")
    .setActionName("showActivity")
    .build()
    .callAsync { cc, result ->
        //此onResult在子线程中运行
    }

//或 异步调用,在主线程执行回调
val callId = CC.obtainBuilder("ComponentA")
    .setActionName("login")
    .build()
    .callAsyncCallbackOnMainThread { cc, result -> //此onResult在主线程中运行
        val toast =
            "login " + if (result.isSuccess) "success" else "failed"
        Toast.makeText(this@MainActivity, toast, Toast.LENGTH_SHORT).show()
    }

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一场雪ycx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值