Android 组件化和插件化详解

1. Android 组件化

    1. 组件化开发可以有效降低代码模块的耦合度,使代码架构更加清晰,同时模块化的编译可以有效减少编译时间,当然总的编译时间是不会减少的,只是App模块化之后开发某个模块时,只需要编译特定模块,可以快速编译调试
    1. 将一个Module拆分成若干个Module,由主App提供统一的入口,每个拆分后的Module都依赖共享的Common依赖库,通过相关配置,各个Module可以独立运行调试,也可以供主App依赖使用。
    1. ARouter 原理

ARouter 核心实现思路是,我们在代码里加入的 @Route 注解,会在编译时期通 过 apt生成一些存储 pathactivityClass映射关系的类文件,然后 app进程启动的时候会拿到这些类文件,把保存这些映射关系的数据读到内存里(保存在 map 里),然后在进行路由跳转的时候,通过 build() 方法传入要到达页面的路由 地址,ARouter会通过它自己存储的路由表找到路由地址对应的 Activity.class(activity.class = map.get(path)),然后 new Intent(),当调用 ARouterwithString()方法它的内部会调用 intent.putExtra(String name, String value), 调用 navigation()方法,它的内部会调用startActivity(intent)进行跳转,这样便可 以实现两个相互没有依赖的 module顺利的启动对方的 Activity.

3.1 ARouter的原理就是所有的moudle都引用ARouter,然后再moudle中去生成一个映射表,然后再把这个映射表传到ARouter
3.2 映射表生成 , 我们一般配置ARouter会这样写

@Route(path = xxx/xxx)
public class xxx{
    ......
  }

3.3 发起跳转

ARouter.getInstance().build("/user/UserMainActivity").navigation()

ARouter的代码要简洁很多,完全不需要手动注册路由就可完成跳转,它是怎么做到的呢?
3.4 很神奇!与前篇我们实现的路由相比,ARouter的代码要简洁很多,完全不需要手动注册路由就可完成跳转,它是怎么做到的呢?
通过跟进navigation()函数调用过程,我们把目光聚焦到两个容器中:

  // ARouter源码
class Warehouse {
    // Cache route and metas
    //用于存储所有的路由组
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    //用于存储已注册的所有路由
    static Map<String, RouteMeta> routes = new HashMap<>();  
  
    ...
}

public interface IRouteGroup {
    /**
     * Fill the atlas with routes in group.
     * atlas用于存储当前组里的所有路由,实际传入的就是Warehouse.routes
     */
    void loadInto(Map<String, RouteMeta> atlas);
}
 // 路由包装类,路由目标的Class对象就存储在这里面
public class RouteMeta {
    private RouteType type;         // Type of route
    private Element rawType;        // Raw type of route
    private Class<?> destination;   // Destination
    private String path;            // Path of route
    private String group;           // Group of route
    private int priority = -1;      // The smaller the number, the higher the priority
    private int extra;              // Extra data
    private Map<String, Integer> paramsType;  // Param type
    private String name;
    
    ...
}
  • ARouter对路由提出了分组概念,上面 UserMainActivity就属于user组下,当路由path存在2级及以上时,group字段也可以省略,ARouter默认会使用第一个反斜杠后面的path作为组名
// group可省略不写
@Route(path = "/user/UserMainActivity")
class UserMainActivity : AppCompatActivity() {
      ...
}
  • 一般情况下,我们会将同一模块的路由划分在同一个组下,例如App模块下的所有路由都在“app”这个分组下 , user模块的路由都在“user”分组下;当然,同一模块拥有多个分组也是完全可行的,只要保证与其它模块中的路由分组不重名即可

分析这两个容器的作用,大致如下:
1、当传入path进行跳转时,优先从Warehouse.routes中直接获取路由对象;
2、路由对象不存在,就需要通过Warehouse.groupsIndex路由组来完成注册功能
3、注册成功后,当前path所在组的所有路由都将存储到Warehouse.routes中;
4、回到第1步,获取路由对象;
5、读取路由对象信息;
6、完成跳转

2. Android 插件化

    1. 随着apk越来越大,各种业务逻辑越来越繁杂,会达到apk开发的一个瓶颈;从业务上说,业务的繁杂会导致代码急剧的膨胀,当代码中的方法数超过65535时,就无法再容纳创建新的方法。插件化时将 apk 分为宿主和插件部分,插件在需要的时候才加载进来.
    1. 插件化的优点
  • 宿主和插件分开编译
  • 并发开发,宿主和插件都是apk,开发是互不影响的,只需要宿主给插件一个上下文
  • 动态更新插件,不需要安装,下载之后就可以直接打开
  • 按需下载模块
  • 可以解决方法数或变量数爆棚问题
    1. Android中的ClassLoader
      在Android系统中ClassLoader是用来加载dex文件的,有包含 dex 的 apk 文件以及 jar 文件,dex 文件是一种对class文件优化的产物,在Android中应用打包时会把所有class文件进行合并、优化(把不同的class文件重复的东西只保留一份),然后生成一个最终的class.dex文件
    1. PathClassLoader用来加载系统类和应用程序类,可以加载已经安装的 apk目录下的 dex文件
public class PathClassLoader extends BaseDexClassLoader {
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}
    1. DexClassLoader用来加载 dex文件,可以从存储空间加载 dex文件。
public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}

插件化中一般使用的是 DexClassLoader

3. 组件化和插件化的区别 ?

  1. 组件化 : 是将一个App分成多个模块,每个模块都是一个组件(module),开发过程中可以让这些组件相互依赖或独立编译、调试部分组件,但是这些组件最终会合并成一个完整的Apk去发布到应用市场。
  2. 插件化 : 是将整个App拆分成很多模块,每个模块都是一个Apk(组件化的每个模块是一个lib),最终打包的时候将宿主Apk和插件Apk分开打包,只需发布宿主Apk到应用市场,插件Apk通过动态按需下发到宿主Apk
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容