zoukankan      html  css  js  c++  java
  • 在Android的App中动态的加载Java类

    原文的地址:http://yenliangl.blogspot.com/2009/11/dynamic-loading-of-classes-in-your.html
    我正在编写一个应用程序能够加载别人开发的应用插件。对于应用程序思路的实现,我首先想到的是使用 Class.forName 以及java.lang.reflective中的提供的方法。我比较倾向于使用 Class.forName(),像下面一样:

    try {
             Class<?> handler = Class.forName(handlerClassName);
             Method m = handler.getDeclaredMethod(
                    "addMyPreferences",
                    Class.forName("android.content.Context"),
                    Class.forName("android.preference.PreferenceCategory"),
                    Class.forName("java.lang.String"));
             m.invoke(handler.newInstance(), this, mExtraSettingsCategory, defaultValue);
         } catch(ClassNotFoundException e) {
            // .....
         }
         // other exceptions that may be thrown by reflective API.
    

    但是经过实践发现,上面的代码会出现ClassNotFoundException的异常。我怎么办?一个比较麻烦的问题在我的脑海里闪现,我猜想是不是别的开发者也会和我遇到同样的问题,于是我就谷歌查询,发现一个文档对我理解:为什么上面的代码会抛出ClassNotFoundException异常非常有帮助(点击这里)。
    该文档上说,Java的基本动态加载模块依赖于java的parent-chaild层次结构和ClassLoader类。通过日志打印出类加载的顺序(层次)对于理解类的加载很有帮助。因此,我就这么做了。

    ClassLoader cl = this.getClass().getClassLoader();
    while (cl != null) {
        Log.d(TAG, "====> class loader: " + cl.getClass());
        cl = cl.getParent();
    }


    在我的电脑上,在类加载的时候打印显示加载了2个类分别是 dalvik.system.PathClassLoader类 和 java.lang.BootClassLoader类。最有趣的事情是使用 PathClassLoader类。查看它的文档发现 PathClassLoader类能够接受不同类型的值作为它的构造函数的参数,直接从文档上复制过来看:

    public PathClassLoader  (String path, ClassLoader parent)
    
    Creates a PathClassLoader that operates on a given list of files and directories. This method is equivalent to calling PathClassLoader(String, String, ClassLoader) with a null value for the second argument (see description there).
    
        * Directories containing classes or resources.
        * JAR/ZIP/APK files, possibly containing a "classes.dex" file.
        * "classes.dex" files.


    好啦,基于文档上面的规定说明,我猜测使用apk文件名构造PathClassLoader 类实例,并且这个apk应用是在传递中创建,如下:

    PathClassLoader("/data/app/org.startsmall.myapp.apk",
                    ClassLoader.getSystemClassLoader());

    因此,如果我想使用Class.forName()就应该从第三方应用开发者哪里知道要加载的类的名字,并且必须重新构造PathClassLoader 类实例从我的apk应用和第三方应用中加载类,下面是示例代码:

    final String apkFiles =
                "/data/app/org.startsmall.myapp.apk:" + // myself
                // handlers defined by other developers
                "/data/app/" + handlerClassName.substring(0, lastDotPos) + ".apk";
    
            dalvik.system.PathClassLoader myClassLoader =
                new dalvik.system.PathClassLoader(
                    apkFiles,
                    ClassLoader.getSystemClassLoader());
    
             // ...
    
            try {
                Class<?> handler =
                    Class.forName(handlerClassName, true, classLoader);
    
                // Call reflective APIs.
    
           } catch (ClassNotFoundException e) {
                // .....
           }

    经过上面这些经验和错误,我的代码终于可以加载第三方的类和方法,并且可以执行达到预期的效果。


    注:翻译的不好,请无视直接看原文。




  • 相关阅读:
    优化页面响应时间
    php性能优化
    加快compser install 和update的方法
    好用的类库
    php会话(session)实现原理
    mysql引擎
    数据库事物四大特性
    数据库索引
    insert和insertSelective区别
    java面试题之int和Integer的区别
  • 原文地址:https://www.cnblogs.com/csnd/p/11800737.html
Copyright © 2011-2022 走看看