Java中也有類加載器ClassLoader,其作用是動態裝載Class文件,當我們從網絡下載Class文件,或者在編譯時不參與而在運行時動態調用時就需要用類加載器。由於Android對class文件進行了重新打包和優化,最終APK文件中包含的是dex文件,加載這種文件就需要用到DexClassLoader。
DexClassLoader(dexPath, optimizedDirectory, libraryPath, parent)
dexPath:目標類所在的APK或者jar包,/.../xxx.jar
optimizedDirectory:從APK或者jar解壓出來的dex文件存放路徑
libraryPath:native庫路徑,可以為null
parent:父類裝載器,一般為當前類的裝載器、
插件類Plugin用於在運行時由宿主程序調用
public class Plugin { public int add(int a, int b) { return a+b; } }使用jar命令將其打包成jar文件
jar -cvf plugin.jar com/dl/plugin/Plugin.class使用dx命令將其轉化為android中的類格式dex文件
dx --dex --output=f:\dynamic.jar f:\Plugin.jar將其放到手機目錄中,比如放到根目錄
adb push F:\dynamic.jar /
在宿主程序中動態加載調用插件類Plugin的add函數
DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader()); clazz = loader.loadClass("com.dl.plugin.Plugin"); Method add = clazz.getMethod("add", Integer.TYPE,Integer.TYPE); int result = (Integer) add.invoke(clazz.newInstance(), 1,1);首先動態加載Plugin類,然后通過反射調用add方法,完整代碼如下
private Button btn; private Class<?> clazz; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { if (clazz == null) { DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader()); clazz = loader.loadClass("com.dl.plugin.Plugin"); } Method add = clazz.getMethod("add", Integer.TYPE,Integer.TYPE); int result = (Integer) add.invoke(clazz.newInstance(), 1,1); Toast.makeText(MainActivity.this, result+"", 0).show(); } catch (Exception e) { e.printStackTrace(); } } }); }
上面使用反射進行函數調用有些復雜,可以使用接口進行更方便的調用還能保持動態加載的靈活性。項目結構如下,保證接口IPlugin類名一致,包括包名。也可以通過引入jar包的形式來做。


於是就可以通過如下方式調用插件類中的代碼了。
DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader()); clazz = loader.loadClass("com.dl.plugin.Plugin"); IPlugin obj = (IPlugin) clazz.newInstance(); int result = obj.add(1, 1);
效果: