android 動態加載技術demo

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.定義接口,定義實現類。

Paste_Image.png

將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文件的文件格式。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容