• Android 插件化与反射机制


    一、反射机制定义

      Java反射机制就是在程序运行状态中,对于任意一个类,都能知道这个类的所有的属性和方法;对于任意一个对象,都能任意的调用对象中属性和方法;这种动态获取类信息以及动态调用对象中任意的属性和方法的功能就是Java的反射机制。

      在Java中使用ClassLoader类动态装载Class文件,ClassLoader是标准Java SDK中的类,借助这个类可以装载任意的Class文件,在ClassLoader初始化时要指定Class文件的路径。

      在Android中使用DexClassLoader和PathClassLoader动态的装载Class文件。

      DexClassLoader和PathClassLoader的区别:

      1. DexClassLoader是动态的装载指定的SD卡中的Apk、Jar、dex文件(未安装)。

      2. PathClassLoader是动态装载本地系统中已经安装的Apk。

      Java中的反射实现太过于冗长,可以使用开源的jOOR反射库(https://github.com/jOOQ/jOOR)。 

    二、类加载器DexClassloader和PathClassloader继承关系

    三、插件化所解决问题

      1. 动态加载apk

        到指定的SD卡中加载Apk程序。

      2. 资源加载

        通过AssetsManager类加载资源。

      3. 代码加载

        就是类加载机制,Android与Java中不同,在Android中有生命周期。    

    四、代码示例

      1. 类加载

     1     @SuppressLint("NewApi")
     2     protected void launchTargetActivity(final String className) {
     3         Log.d(TAG, "start launchTargetActivity, className=" + className);
     4         File dexOutputDir = this.getDir("dex", 0);
     5         final String dexOutputPath = dexOutputDir.getAbsolutePath();
     6         ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();
     7         DexClassLoader dexClassLoader = new DexClassLoader(mDexPath,
     8                 dexOutputPath, null, localClassLoader);
     9         try {
    10             Class<?> localClass = dexClassLoader.loadClass(className);
    11             Constructor<?> localConstructor = localClass
    12                     .getConstructor(new Class[] {});
    13             Object instance = localConstructor.newInstance(new Object[] {});
    14             Log.d(TAG, "instance = " + instance);
    15 
    16             Method setProxy = localClass.getMethod("setProxy",
    17                     new Class[] { Activity.class });
    18             setProxy.setAccessible(true);
    19             setProxy.invoke(instance, new Object[] { this });
    20 
    21             Method onCreate = localClass.getDeclaredMethod("onCreate",
    22                     new Class[] { Bundle.class });
    23             onCreate.setAccessible(true);
    24             Bundle bundle = new Bundle();
    25             bundle.putInt(FROM, FROM_EXTERNAL);
    26             onCreate.invoke(instance, new Object[] { bundle });
    27         } catch (Exception e) {
    28             e.printStackTrace();
    29         }
    30     }

      2. 资源加载

     1     protected void loadResources() {
     2         try {
     3             AssetManager assetManager = AssetManager.class.newInstance();
     4             Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
     5             addAssetPath.invoke(assetManager, mDexPath);
     6             mAssetManager = assetManager;
     7         } catch (Exception e) {
     8             e.printStackTrace();
     9         }
    10         Resources superRes = super.getResources();
    11         mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),
    12                 superRes.getConfiguration());
    13         mTheme = mResources.newTheme();
    14         mTheme.setTo(super.getTheme());
    15     }

      3. 代码加载 

     1     protected void instantiateLifecircleMethods(Class<?> localClass) {
     2         String[] methodNames = new String[] {
     3                 "onRestart",
     4                 "onStart",
     5                 "onResume",
     6                 "onPause",
     7                 "onStop",
     8                 "onDestory"
     9         };
    10         for (String methodName : methodNames) {
    11             Method method = null;
    12             try {
    13                 method = localClass.getDeclaredMethod(methodName, new Class[] { });
    14                 method.setAccessible(true);
    15             } catch (NoSuchMethodException e) {
    16                 e.printStackTrace();
    17             }
    18             mActivityLifecircleMethods.put(methodName, method);
    19         }
    20 
    21         Method onCreate = null;
    22         try {
    23             onCreate = localClass.getDeclaredMethod("onCreate", new Class[] { Bundle.class });
    24             onCreate.setAccessible(true);
    25         } catch (NoSuchMethodException e) {
    26             e.printStackTrace();
    27         }
    28         mActivityLifecircleMethods.put("onCreate", onCreate);
    29 
    30         Method onActivityResult = null;
    31         try {
    32             onActivityResult = localClass.getDeclaredMethod("onActivityResult",
    33                     new Class[] { int.class, int.class, Intent.class });
    34             onActivityResult.setAccessible(true);
    35         } catch (NoSuchMethodException e) {
    36             e.printStackTrace();
    37         }
    38         mActivityLifecircleMethods.put("onActivityResult", onActivityResult);
    39     }
    40 
    41     @Override
    42     protected void onResume() {
    43         super.onResume();
    44         Method onResume = (Method) mActivityLifecircleMethods.get("onResume");
    45         if (onResume != null) {
    46             try {
    47                 onResume.invoke(mRemoteActivity, new Object[] { });
    48             } catch (Exception e) {
    49                 e.printStackTrace();
    50             }
    51         }
    52     }
    53 
    54     @Override
    55     protected void onPause() {
    56         Method onPause = (Method) mActivityLifecircleMethods.get("onPause");
    57         if (onPause != null) {
    58             try {
    59                 onPause.invoke(mRemoteActivity, new Object[] { });
    60             } catch (Exception e) {
    61                 e.printStackTrace();
    62             }
    63         }
    64         super.onPause();
    65     }

     

  • 相关阅读:
    Linux使用lrzsz上传下载文件
    开发Wordpress主题时没有特色图片的功能
    Windows10重启之后总是将默认浏览器设置为IE
    C#泛型类的类型约束
    CentOS给网站配置Https证书
    从微软官网下载VS离线安装包的方法
    Azure Sql Database为某个数据库创建单独的访问账户
    VS2017/2019 Product Key
    VMware Workstation/Fusion 14/15 密钥
    将DataTable进行分页并生成新的DataTable
  • 原文地址:https://www.cnblogs.com/naray/p/8856374.html
Copyright © 2020-2023  润新知