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.定义接口,定义实现类。

android 动态加载技术demo_第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文件的文件格式。

你可能感兴趣的:(android 动态加载技术demo)