Android
插件化的好處
大家都知道Android能編譯的方法不能超出65535.如果超出了會(huì)影響編譯。當(dāng)然解決這個(gè)方法有很多,其中最常用的就是goole的mulitDex的jar包,另外就是常用的插件化。再者,插件化可以很大程度上減少功能模塊的耦合,還可以起到精簡apk包的大小。當(dāng)然這個(gè)有時(shí)候要結(jié)合服務(wù)器下發(fā)一起使用。最后想說的Android的插件化其實(shí)就是根據(jù)Java的classloder原理去實(shí)現(xiàn)的。
Android 插件化方法
一般來說主要是通過以下兩個(gè)Android自帶的類去實(shí)現(xiàn)。
1. DexClassLoader
從類名可以看出,這個(gè)類肯定是跟dex文件有關(guān)的。不錯(cuò),但他也可以識(shí)別.jar, .apk .dex文件。
實(shí)例說明:
step1:自己隨意寫一個(gè)plugin apk。 但是這個(gè)插件apk必須有明確的action。再者就是已經(jīng)安裝。
step2:寫自己的主程序,在主程序里要通過包名獲取插件的資源文件地址,包名等。
如:Intent intent = new Intent(XXX)//要寫入插件的action名字
List infos =getPackmanger().queryAllActivits(intent, 0) // 獲取所有的activity
然后就是過濾到插件的activityinfo 然后拿到dexcladdloader所需要的參數(shù)
DexClassLoader dexcl =newDexClassLoader(sourceDir, outDir,54libraryDir,this.getClass().getClassLoader());
之后就是通過dexloader的實(shí)例去找到plugin的dex文件(在這里是通過包名加類名)
Class <> cllassloader = dexcl.loadclass() // 填入要傳入的參數(shù)。
然后調(diào)用插件的方法
2. PathClassLoader
和DexClassLoader相反,不能直接從zip文件讀取dex文件,只能直接操作dex文件。當(dāng)然如果對(duì)于已經(jīng)安裝的apk插件,也是可以操作的,原因不言而語,因?yàn)榘惭b后的apk在緩存里有dex文件。
pathClassLoader的加載方式和dexclassloader差不多,也需要獲取對(duì)應(yīng)的插件activity,也需要實(shí)例一個(gè)classloader。只不過是傳入的參數(shù)不一樣罷了。在這里就不舉實(shí)例說明了。
3. 共同點(diǎn)
其實(shí)所有的加載都是通過dexFile類去加載的。但是為何不直接用dexfile直接loadclass。看下源代碼:
public class loadClass(String name, CalssLoader loader) {
String splashName=name.replace('.', '/');
return loadCalssBinaryName(splashName, loader);
}
dexclassloader 和pathcalssloader都不會(huì)直接調(diào)dexfile的loadclass方法,他們是通過父類去調(diào)用,如果已經(jīng)存在就直接返回一個(gè)。
pathClassLoader是通過構(gòu)造函數(shù)newDexFile(path)來產(chǎn)生DexFile對(duì)象的;而DexClassLoader則是通過其靜態(tài)方法loadDex(path,outpath, 0)得到DexFile對(duì)象。這兩者的區(qū)別在于DexClassLoader需要提供一個(gè)可寫的outpath路徑,用來釋放.apk包或者.jar包中的dex文件。
另外,PathClassLoader在加載類時(shí)調(diào)用的是DexFile的loadClassBinaryName,而DexClassLoader調(diào)用的是loadClass。因此,在使用PathClassLoader時(shí)類全名需要用”/”替換”.”
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;
}