Android插件化研究

Android

插件化的好处

大家都知道Android能编译的方法不能超出65535.如果超出了会影响编译。当然解决这个方法有很多,其中最常用的就是goole的mulitDex的jar包,另外就是常用的插件化。再者,插件化可以很大程度上减少功能模块的耦合,还可以起到精简apk包的大小。当然这个有时候要结合服务器下发一起使用。最后想说的Android的插件化其实就是根据Java的classloder原理去实现的。

Android 插件化方法

一般来说主要是通过以下两个Android自带的类去实现。

1. DexClassLoader

从类名可以看出,这个类肯定是跟dex文件有关的。不错,但他也可以识别.jar, .apk .dex文件。

实例说明:

step1:自己随意写一个plugin apk。 但是这个插件apk必须有明确的action。再者就是已经安装。

step2:写自己的主程序,在主程序里要通过包名获取插件的资源文件地址,包名等。

如:Intent intent = new Intent(XXX)//要写入插件的action名字

List infos =getPackmanger().queryAllActivits(intent, 0) // 获取所有的activity

然后就是过滤到插件的activityinfo 然后拿到dexcladdloader所需要的参数

DexClassLoader dexcl =newDexClassLoader(sourceDir, outDir,54libraryDir,this.getClass().getClassLoader());

之后就是通过dexloader的实例去找到plugin的dex文件(在这里是通过包名加类名)

Class <> cllassloader = dexcl.loadclass() // 填入要传入的参数。

然后调用插件的方法

2. PathClassLoader

和DexClassLoader相反,不能直接从zip文件读取dex文件,只能直接操作dex文件。当然如果对于已经安装的apk插件,也是可以操作的,原因不言而语,因为安装后的apk在缓存里有dex文件。

pathClassLoader的加载方式和dexclassloader差不多,也需要获取对应的插件activity,也需要实例一个classloader。只不过是传入的参数不一样罢了。在这里就不举实例说明了。

3. 共同点

其实所有的加载都是通过dexFile类去加载的。但是为何不直接用dexfile直接loadclass。看下源代码:

public class loadClass(String name, CalssLoader loader) {

String splashName=name.replace('.', '/');

return loadCalssBinaryName(splashName, loader);

}

dexclassloader 和pathcalssloader都不会直接调dexfile的loadclass方法,他们是通过父类去调用,如果已经存在就直接返回一个。

pathClassLoader是通过构造函数newDexFile(path)来产生DexFile对象的;而DexClassLoader则是通过其静态方法loadDex(path,outpath, 0)得到DexFile对象。这两者的区别在于DexClassLoader需要提供一个可写的outpath路径,用来释放.apk包或者.jar包中的dex文件。

另外,PathClassLoader在加载类时调用的是DexFile的loadClassBinaryName,而DexClassLoader调用的是loadClass。因此,在使用PathClassLoader时类全名需要用”/”替换”.”

4. DexFile源码:

packageandroid.dalvik;

importjava.io.File;

importjava.io.IOException;

importjava.security.ProtectionDomain;

publicfinalclassDexFile

{

publicDexFile(File file)

throwsIOException

{

this(file.getPath());

}

publicDexFile(String fileName)

throwsIOException

{

String

wantDex =

System.getProperty("android.vm.dexfile","false");

if(!wantDex.equals("true"))

{

thrownewUnsupportedOperationException("No dex in

this VM");

}else

{

mCookie

= openDexFile(fileName);

return;

}

}

publicvoidclose()

throwsIOException

{

closeDexFile(mCookie);

}

publicClass loadClass(String name, ClassLoader loader)

{

returndefineClass(name, loader, mCookie,null);

}

privatestaticnativeClass

defineClass(String s, ClassLoader classloader,inti, ProtectionDomain

protectiondomain);

protectedvoidfinalize()

throwsIOException

{

close();

}

privatestaticnativeintopenDexFile(String s)

throwsIOException;

privatestaticnativevoidcloseDexFile(inti);

privatefinalintmCookie;

}

你可能感兴趣的:(Android插件化研究)