深入理解Android插件化技术

论坛 期权论坛     
选择匿名的用户   2021-5-22 22:12   146   0
<p>插件化技术可以说是Android高级工程师所必须具备的技能之一,从2012年插件化概念的提出(Android版本),到2016年插件化的百花争艳,可以说,插件化技术引领着Android技术的进步。本篇文章转载自腾讯bugly,觉得写得不错,转载分享给大家。</p>
<h1 id="1">插件化提要</h1>
<p><img alt="这里写图片描述" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-b965c44f41ed1b9c7eb057b76ebba02b"></p>
<p>可以说,插件化技术涉及得非常广泛,其中最核心的就是Android的类加载机制和反射机制,相关原理请大家自行百度。</p>
<h2 id="2">插件化发展历史</h2>
<p>插件化技术最初源于免安装运行apk的想法,这个免安装的apk可以理解为插件。支持插件化的app可以在运行时加载和运行插件,这样便可以将app中一些不常用的功能模块做成插件,一方面减小了安装包的大小,另一方面可以实现app功能的动态扩展。想要实现插件化,主要是解决下面三个问题:</p>
<ul><li>插件中代码的加载和与主工程的互相调用</li><li>插件中资源的加载和与主工程的互相访问</li><li>四大组件生命周期的管理</li></ul>
<p>下面是比较出名的几个开源的插件化框架,按照出现的时间排序。研究它们的实现原理,可以大致看出插件化技术的发展,根据实现原理可以将这几个框架划分成了三代。<br><img alt="这里写图片描述" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-d039538dbf5dfe7fd46086ad0b9634cb"></p>
<p><strong>第一代</strong>:dynamic-load-apk最早使用ProxyActivity这种静态代理技术,由ProxyActivity去控制插件中PluginActivity的生命周期。该种方式缺点明显,插件中的activity必须继承PluginActivity,开发时要小心处理context。而DroidPlugin通过Hook系统服务的方式启动插件中的Activity,使得开发插件的过程和开发普通的app没有什么区别,但是由于hook过多系统服务,异常复杂且不够稳定。<br><strong>第二代</strong>:为了同时达到插件开发的低侵入性(像开发普通app一样开发插件)和框架的稳定性,在实现原理上都是趋近于选择尽量少的hook,并通过在manifest中预埋一些组件实现对四大组件的插件化。另外各个框架根据其设计思想都做了不同程度的扩展,其中Small更是做成了一个跨平台,组件化的开发框架。<br><strong>第三代</strong>:VirtualApp比较厉害,能够完全模拟app的运行环境,能够实现app的免安装运行和双开技术。Atlas是阿里今年开源出来的一个结合组件化和热修复技术的一个app基础框架,其广泛的应用与阿里系的各个app,其号称是一个容器化框架。</p>
<h1 id="3">插件化原理</h1>
<h2 id="4">类加载</h2>
<p>Android中常用的有两种类加载器,DexClassLoader和PathClassLoader,它们都继承于BaseDexClassLoader。相关源码如下:</p>
<pre class="blockcode"><code>// DexClassLoaderpublic class DexClassLoader extends BaseDexClassLoader {    public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}
// PathClassLoader

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);
    }
}</code></pre>
<p>区别在于调用父类构造器时,DexClassLoader多传了一个optimizedDirectory参数,这个目录必须是内部存储路径,用来缓存系统创建的Dex文件。而PathClassLoader该参数为null,只能加载内部存储目录的Dex文件。所以我们可以用DexClassLoader去加载外部的apk,用法如下:</p>
<pre class="blockcode"><code>//第一个参数为apk的文件目录
//第二个参数为内部存储目录
//第三个为库文件的存储目录
//第四个参数为父加载器
new DexClassLoader(apk.getAbsolutePath(), dexOutputPath, libsDir.getAbsolutePath(), parent)</code></pre>
<p>其实,关于类加载更详细的内容,笔者也深入剖析过,可以查看下面的链接:<a href="https://yq.aliyun.com/go/articleRenderRedirect?url&#61;http%3A%2F%2Fblog.csdn.net%2Fxiangzhihong8%2Farticle%2Fdetails%2F52880327">类加载机制详解</a></p>
<h2 id="5">双亲委托机制</h2>
<p>ClassLoader调用loadClass方法加载类,代码如下:</p>
<pre class="blockcode"><code>protected Class&lt;?&gt; loadClass(String className, boolean resolve) throws ClassNotFoundException {
       //首先从已经加载的类中查找
        Class&lt;?&gt; clazz &#61; findLoadedClass(className);   
    if (clazz &#61;&#61; null) {
            ClassNotFoundException sup
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP