1.引言
前面寫了很多關于java類加載機制的筆記。今天又看了下android動態加載,發現和java加載類真是貼切,因此看了很順暢,故而按照博客的指示寫了一個小demo,再次記錄下。
2.正題
動態加載技術,因為使用到的類是外來的類,主app中沒得這個類。因此無法在主app中事先引用進來。所以反射是我們經常想到的解決辦法,博客也提出了接口的方法。也對反射的確是有點慢。
動態加載訪問api:1.反射 2.接口。
回顧前面的jvm加載類的過程我們知道classloader,通過調研loadClass,進而繼續調用findClass,然后findClass 在調用defineClass。最終可以在jvm的堆中形成Class對象。。而Android的dvm中并沒得defineClass,它有前倆步驟,但是沒得defineClass的過程,dvm是將class文件,直接打包成dex文件。當運行代碼的時候發現要用到某一個Class文件。dvm會在dex找到對應的Class文件,然后通過加載器將dex 轉換成Class對象。
實驗:用接口的方式實現動態加載技術。
2.1.定義接口,定義實現類。
將Dynamic類打包成jar包的時候,折騰了一番。發現網上打包成jar的都額外的建立了一個Module。然后設置task makeJar。我按照網上的教程沒實踐成功,最后把Class.jar 拿出來,然后通過刪除 保留我想要的。
將Dynamic 和IDynamic 分別打包成Dynamic.jar 和 IDynamic.jar .
前面說過dvm只認識dex文件。所以我們將Dynamic.jar 進一步轉換成DynamicDex.jar。用到的工具是sdk,plateform-tool的dx 工具。執行
dx --dex --output=dynamic_temp.jar(輸出的名字) dynamic.jar(最開始的名字)
在同一個文件夾下可以這樣,不同的話要帶上路徑
然后將IDynamic.jar 以第三方jar形式導入到項目中。
前期準備工作就是這些。。
2.2.加載外來的類
DexClassLoader 和PathClassLoader的區別是,DexClassLoader能加載外來的沒有安裝的apk,jar。 而PathClassLoader只能加載已經安裝的。
因此選擇DexClassLoader作為類加載器。
DexClassLoader:
DexClassLoader dexClassLoader=new DexClassLoader(outDexJar,appFiles,null,getClassLoader());
outDexJar參數: 外來的apk,jar的文件路徑。
appFiles:app的包名下面的Files文件夾。通過以下代碼獲取
getApplicationContext().getFilesDir().getAbsolutePath();//app的包名下面的Files文件夾
getApplicationContext().getCacheDir().getAbsolutePath();//app包名下面的Caches文件夾
```java
public class MainActivity extends AppCompatActivity{
private IDynamic iDynamic;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button= (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String outDexJar= Environment.getExternalStorageDirectory().getAbsolutePath()+"/test"+"/Dynamic.jar";
File f=new File(outDexJar);
if (f.exists()){
String ss="123";
}
String appFiles=getApplicationContext().getCacheDir().getAbsolutePath();
ClassLoader classLoader=getClassLoader();
String classloadName=classLoader.toString();
DexClassLoader dexClassLoader=new DexClassLoader(outDexJar,appFiles,null,getClassLoader());
try {
Class c=dexClassLoader.loadClass("xinyi.com.mylibrary.Dynamic");//通過loadClass,找到dex對應的Class,然后變成Class
try {
iDynamic= (IDynamic) c.newInstance();
Toast.makeText(MainActivity.this,iDynamic.helloWorld(), Toast.LENGTH_SHORT).show();;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
}
}
好了這個demo很簡單。不過我在寫博客的過程中,想到一個問題。通過類加載器將Class文件----->dex 文件。然后在使用的過程中又是將dex文件轉化成Class文件。這不是多此一舉嗎? 當然肯定不是多此一舉,dex文件必然有一些好處。下一篇 記錄下dex的優點,以及dex文件的文件格式。