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;
}