客户端开发给人的印象往往是小巧,快速奔跑。但随着产品的发展,目前产生了大量的门户型客户端。功能模块持续集成,开发人员迅速增长。不同的开发小组开发不同的功能模块,甚至还有其他客户端集成进入。能做到功能模块开发和发布的独立,能像Html5一样能帅气的解决bug并动态更新到用户的手机,一直是客户端开发的梦寐以求的特性。


一、问题提出
     一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来越多,APK安装包也越来越大,用户在使用过程中也没有办法选择性的加载自己需要的功能模块。此时可能就需要考虑如何分拆整个应用了。
     当前问题:
          1.代码越来越庞大,很难维护
          2.需求越来越多,某一模块的小改动都要重新发布版本,发布时间越来越不可控。

3.项目中某一段代码牵涉模块越来越多,应对bug反应越来越慢。

     潜在问题:
          早期的Dalvik VM内部使用short类型变量来标识方法的id,dex限制了程序的最大方法数是65535,如果超过最大限制,无法编译,(此外补充一点,之前做Framework开发时候,曾遇到多方法数量超过65535编译不通过,修改makefile,从外部(一般是源码目录下Vender/xx/xx/xx...)加载类既可以解决)。

二、解决方案提出
     1.用Html5代替部分逻辑
     2.删除无用代码,减少方法数
     3.插件化,将一个 App 划分为多个插件(Apk 或相关格式)

     前两种方法在某种条件下可以解决问题,但是治标不治本。下面我们重点说一下Android插件化开发。


三、Android插件化


     Android 插件化 —— 指将一个程序划分为不同的部分,比如一般 App 的皮肤样式就可以看成一个插件

     Android 组件化 —— 这个概念实际跟上面相差不那么明显,组件和插件较大的区别就是:组件是指通用及复用性较高的构件,比如图片缓存就可以看成一个组件被多个 App 共用

     Android 动态加载 —— 这个实际是更高层次的概念,也有叫法是热加载或 Android 动态部署,指容器(App)在运⾏状态下动态加载某个模块,从而新增功能或改变某⼀部分行为  


     在java开发中随处可见使用jar包的插件机制进行开发,但在android中,目前较成熟的插件机制基本没有,看到的帖子中提到了重写dexclassloader可以完美的解决插件问题,但都只简要描述了原理,没有源码或关键代码,下面对网络中的思路进行总结.

目前插件包有两种格式:一种是apk,一种是dex包.对插件的接入机制来说也有两种:一种是需要安装,一种是不需要安装.结合插件包的格式来说插件的方式只有三种:1,apk安装,2,apk不安装,3,dex包.三种方式其实主要是解决两个方面的问题:1,加载插件中的类,2,加载插件中的资源.第一个加载类的问题,这三个方式都可以很好的解决.但目前三种方式都没有很完美的解决第2个问题.



     1,apk安装方式.插件apk安装后,可以在主程序中通过包名加载到插件的context,有了插件的context就可以解决加载插件资源的问题.但出现的新问题是:如果插件a,b,c间公用一个底层jar包,那么在abc间传送数据时,需要进行序列化和反序列化,因为a中jar包的data类与b中jar包的data类虽然都是同样的jar包也是同样的类,但两个类在java机制来是由不同的classloader加载的,是不同的类.那么就会出现插件间jar包冗余和数据传递的效率不好问题.总之能解决问题.



     2,apk不安装,这个是不推荐的方式.可以通过dexclassloader加载到插件a中的类,但插件没有安装就无法获得插件apk的context,也就无法加载到资源,网络上有牛人通过将主程序的context替换关键的对象(如classloader,assertmanager等),伪造成插件的context,然后通过伪context也可以获得插件资源.目前个人验证的问题为:获取到的layout资源中的textview显示文本有问题,无法显示在layout设定的文本.同时个人猜测这种hack的方式或许有其它的未知的问题,但不排除高手已经解决了这个问题.



     3,dex包,这个基本是java开发中jar包的方式.同样通过dexclassloader加载到插件中的类,但依旧没有context,也无法加载到资源.要使用布局,只能在插件中使用java代码来写布局.这种方式最简单(1,类似jar包的方式,也可以随意导出单个类的jar包然后转化为dex包,不存在打包成apk需要完整的工程和依赖关系的要求.2,底层的公用jar包所有插件可以公共一个,传递数据不用反复的序列化和反序列化.),也是最复杂的(布局文件全部代码写,难调试,难维护).



四、优缺点
     插件式开发通俗的讲就是把一个很大的app分成n多个比较小的app,其中有一个app是主app。基本上可以理解为让一个apk不安装也可以被运行。只不过这个运行是有很多限制的运行,所以才叫插件否则就叫病毒了。其实在目前淘宝、百度、腾讯、等都有成熟的动态加载框架,包括apkplug,但是它们都是不开源的。

     优点:
     1.模块解耦
     2.解除单个dex函数不能超过 65535的限制
     3.动态升级
     4.高效开发(编译速度更快)

     基于插件的开发列举两个比较突出的优点:
     1、应用程序非常容易扩展,比如一个新的领域要加到旧的应用程序中,只需把这个新的领域做为一个插件,只开发这个小的app就可以了,旧的应用程序可能会原分不动,就连编译打包都不需要。
     2、下载更新特别省流量,假如一个应用程序有10M把它分成两个的话可能每次更新只需要花费5M或者更少的流量就可以更新完。

     追求完美本来就是一种性格缺陷,说在做软件方面没有近乎完美。基于插件开发当然不是插件越多越好能掌控好内聚和耦合度就更好了。插件增加了主应用程序中的逻辑难度。有优点的东西也是有缺点的这是必然。
     
     缺点:
     1.增加了主应用程序的逻辑难度
     2.技术有难度,目前一些成熟的框架都是闭源的



参考资料:
     1.android插件化及动态部署 - ATLAS--伯奎(阿里无线事业部无线技术专家)


     2.怎么将 Android 程序做成插件化的形式?--知乎
     
     3.Android 插件化 动态升级

     4.apkplug框架

     5.Android插件化开发,初入殿堂

     6.Android 插件框架 AtlasForAndroid(阿里使用框架)
     
     Simple Project

Android插件化开发的更多相关文章

  1. Android插件化开发---执行未安装apk中的Service

    欢迎各位增加我的Android开发群[257053751​] 假设你还不知道什么叫插件化开发.那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从总体角度分析了一下 ...

  2. Android 插件化开发(四):插件化实现方案

    在经过上面铺垫后,我们可以尝试整体实现一下插件化了.这里我们先介绍一下最简单的实现插件化的方案. 一.最简单的插件化实现方案 最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下: 1). 合 ...

  3. Android 插件化开发(一):Java 反射技术介绍

    写在前面:学习插件化开发推荐书籍<Android 插件化开发指南>,本系列博客所整理知识部分内容出自此书. 在之前的项目架构的博文中,我们提到了项目插件化架构,提到插件化架构不得不提的到J ...

  4. 《Android插件化开发指南》面世

    本书在京东购买地址:https://item.jd.com/31178047689.html 本书Q群:389329264 (一)这是一本什么书 如果只把本书当作纯粹介绍Android插件化技术的书籍 ...

  5. Android插件化开发之解决OpenAtlas组件在宿主的注冊问题

    OpenAtlas有一个问题,就是四大组件必须在Manifest文件里进行注冊,那么就必定带来一个问题,插件中的组件都要反复在宿主中注冊.像Service,ContentProvider等组件眼下没有 ...

  6. 【我的Android进阶之旅】Android插件化开发学习资料

    1.目前开源的插件开发框架大致有哪些? 1. 任玉刚 的 dynamic-load-apk Github 地址:https://github.com/singwhatiwanna/dynamic-lo ...

  7. Android插件化开发,初入殿堂

    好久没有写博客了,这次准备写写我这几天的研究成果--Android插件化开发框架CJFrameForAndroid. 好久没有写博客了,这次准备写写我这几天的研究成果--Android插件化开发框架C ...

  8. 详解Android插件化开发-资源访问

    动态加载技术(也叫插件化技术),当项目越来越庞大的时候,我们通过插件化开发不仅可以减轻应用的内存和CPU占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块.     通常我们把安卓资源文件制 ...

  9. Android 插件化开发(二):加载外部Dex文件

    在学习Java反射的技术后,我们可以开始更深一步的探究插件化开发了.首先先讲一下Android App的打包流程,然后我们通过一个简单的例子 —— 实现插件化加载外部Dex来完成初级的插件化开发的探索 ...

随机推荐

  1. 谈谈UIView的几个layout方法

    谈谈UIView的几个layout方法-layoutSubviews.layoutIfNeeded.setNeedsLayout...   最近在学习swift做动画,用到constraint的动画, ...

  2. enmo_day_06

    RAC Data Guard (DG) EMC NAS SAN 双活 数据完整性 约束 : 主键 : 非空 且 唯一 非空 : 唯一 : 外键 : 检查 : DISABLE, ENABLE VALID ...

  3. jQuery.extend源码深层分析

    在网站的开发中,经常会自己写一些jQuery插件来方便使用,其中自然少不了一个关键的方法->jQuery.extend(),使用这个方法来扩展jQuery对象. 那么今天就来讲讲这个函数的实现原 ...

  4. E1_1 用邻接矩阵存储有向图,并输出各顶点的出度和入度

    参考书:图论算法理论.实现及应用(北京大学出版社) 输入数据:(test.txt) 程序: /* 邻接矩阵存储有向图 */ #include <cstring> #include < ...

  5. SQL中case when then用法

    sql语句判断方式之一Case.具有两种格式:简单的Case函数.Case搜索函数. 1.简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' E ...

  6. HttpContext.Current.Cache 和HttpRuntime.Cache的区别

    先看MSDN上的解释:      HttpContext.Current.Cache:为当前 HTTP 请求获取Cache对象.      HttpRuntime.Cache:获取当前应用程序的Cac ...

  7. Python 基礎 - if else流程判斷

    hmm~前面講了那麼多,終於可以稍稍的正式進入另一個階段,沒錯,要開始寫判斷式了 這次先從最簡單的判斷式開始,if else 開始- Go 首先,之前有寫有一個簡單的互動式 用戶輸入 的代碼,忘記了嗎 ...

  8. RocketMQ消费者示例程序

    转载请注明出处:http://www.cnblogs.com/xiaodf/ 本博客实现了一个简单的RocketMQ消费者的示例,MQ里存储的是经过Avro序列化的消息数据,程序读取数据并反序列化后, ...

  9. 最短JS判断是否为IE6(IE的写法)

    常用的 JavaScript 检测浏览器为 IE 是哪个版本的代码,包括是否是最人极端厌恶的 ie6 识别与检测.代码如下: var isIE=!!window.ActiveXObject; var ...

  10. Opencv结构与内容

    一.Opencv的结构分类: cxcore.cv.ML(Machine Learning).HighGUI.cvcam.cvaux 二.常见结构的内容与算法: 1.cxcore库(基本结构和算法.XM ...