關於Android插件框架機制的介紹,我打算分幾章來介紹,這是第一篇也就是預熱篇。
Android 插件框架機制系列文章:
Android 插件框架機制之Small
Android 插件框架機制之DroidPluginjavascript
隨着應用的模塊化的不斷增長,APK的體積不斷增加,方法數極可能會引起64K問題(解決方案),谷歌提供的方案並不完美,並且APK的啓動速度會受影響。java
插件化的根本思路就是讓你的應用調用未安裝的apk,jar,dex文件中的方法。
在Android中,系統提供了兩個API可供選擇:android
public class MainActivity extends Activity {
private Activity otherActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
boolean b = false;
if (savedInstanceState != null) {
b = savedInstanceState.getBoolean("KEY_START_FROM_OTHER_ACTIVITY", false);
if (b) {
this.otherActivity.setContentView(new TBSurfaceView(
this.otherActivity));
}
}
if (!b) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
setContentView(new TBSurfaceView(this));
}
}
public void setActivity(Activity paramActivity) {
this.otherActivity = paramActivity;
}
}複製代碼
在被加載的Activity中是否是識別和加載資源文件的,因此不能用佈局文件,只能用一個View。git
public class TBSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder sfh;
private Thread th;
private Canvas canvas;
private Paint paint;
public TBSurfaceView(Context context) {
super(context);
th = new Thread(this);
sfh = this.getHolder();
sfh.addCallback(this);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
this.setKeepScreenOn(true);
}
public void surfaceCreated(SurfaceHolder holder) {
th.start();
}
private void draw() {
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
canvas.drawText("Time: " + System.currentTimeMillis(), 100,
100, paint);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}
public void run() {
while (true) {
draw();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
}複製代碼
而後將生成的apk,不要安裝在手機,而是存入手機,好比咱們就存入sd卡的根目錄,可使用adb命令:github
adb push /Users/xxxxx/file/source/loadActivity/app/build/outputs/apk/app-debug.apk /sdcard/複製代碼
而後咱們新建一個應用,寫一個加載的方法:canvas
public void dex() {
String apkPath = "/sdcard/app-debug.apk";
String optPath = "/mnt/sdcard/";
// String libPath = info.activityInfo.applicationInfo.nativeLibraryDir;
File dexOutputDir = getDir("dex", 0);
DexClassLoader clsLoader = new DexClassLoader(apkPath, dexOutputDir.getAbsolutePath(),
null, this.getClass().getClassLoader());
try {
Class localClass = clsLoader
.loadClass("deep.loadactivity.MainActivity");
mActivityClass = localClass;
Constructor localConstructor = localClass.getConstructor(new Class[] {});
instance = localConstructor.newInstance(new Object[] {});
mActivityInstance = instance;
Method localMethodSetActivity = localClass.getDeclaredMethod(
"setActivity", new Class[] { Activity.class });
localMethodSetActivity.setAccessible(true);
localMethodSetActivity.invoke(instance, new Object[] { this });
Method methodonCreate = localClass.getDeclaredMethod("onCreate", new Class[] { Bundle.class });
methodonCreate.setAccessible(true);
Bundle paramBundle = new Bundle();
paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY", true);
paramBundle.putString("str", "MainActivity");
methodonCreate.invoke(instance, new Object[] { paramBundle });
} catch (Exception e) {
e.printStackTrace();
}
}複製代碼
下面主要說一下DexClassLoader:app
DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)複製代碼
dexPath:被解壓的apk路徑,不能爲空。
optimizedDirectory:解壓後的.dex文件的存儲路徑,不能爲空。
libraryPath:庫文件的的搜索路徑,通常來講是 .so 庫文件的路徑,也能夠指明多個路徑。
parent:父親加載器,通常爲ClassLoader.getSystemClassLoader()。框架
在上面的例子中咱們實際上是演示了一下動態加載Activity的方法,Activity被動態加載後,是沒有生命週期的,只是當作一個類來作處理,由上面程序能夠看出,咱們是手動調用onCreate方法的。
固然,咱們也能夠寫一些其餘類或方法進行調用,不必定非要用Activity。maven
說完了插件機制,咱們也認識到了插件機制的一些不足,就好比剛纔說的,Activity生命週期沒有了,須要手動調用各個方法,那給咱們的開發帶來了不少不方便,可是網上的一些開源框架,解決了這些不方便,將調用的方法,順序封裝好,咱們只管調用便可。
這些框架,我會在後面的文章中詳細演示。ide
利用DexMaker的動態熱部署功能來實現Activity。
這是基於代理的方式實現插件框架的,須要按照必定的規則來開發插件APK。
這是攜程實現的一種多APK/DEX加載的插件框架。
這是360實現的一種插件框架,他能夠直接運行第三方獨立得APK。徹底不須要對APK進行修改或安裝。
這是一個跨平臺的插件化框架。
以上是我對插件調研的一個總結,在後面的演示中,我會將主流的插件化框架進行詳細說明。