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 }