前言java
如同第一章咱們說的,宿主程序經過 dexclassloader 將插件的類加載進來,而後經過反射去調用它的方法,這樣Activity就被當成了一個普通的類來執行了,所以系統再也不接管它的生命週期,也就是說Activity的生命週期函數失效了。針對這樣的問題,有網友想出使用Fragment來解決此問題,Fragment既有相似於Activity的生命週期,又有相似於View的界面,所以選它比較合適,具體的作法是將Fragment加入到宿主的代理Activity內部,其生命週期將徹底由代理Activity來管理,固然採用這種方法的弊端就是:要求apk儘可能採用Fragment來實現,而且在頁面跳轉的時候比較麻煩,所以咱們這裏就放棄了這個作法,咱們依然經過反射的方法來作。 android
實現app
咱們直接看實現吧。ide
首先是在宿主工程的生命週期函數進行反射:函數
1 package com.bryan.host; 2 3 import java.io.File; 4 import java.lang.reflect.Constructor; 5 import java.lang.reflect.InvocationTargetException; 6 import java.lang.reflect.Method; 7 8 import dalvik.system.DexClassLoader; 9 10 import android.annotation.SuppressLint; 11 import android.app.Activity; 12 import android.content.pm.PackageInfo; 13 import android.content.pm.PackageManager; 14 import android.content.res.AssetManager; 15 import android.content.res.Resources; 16 import android.content.res.Resources.Theme; 17 import android.os.Bundle; 18 import android.provider.MediaStore.Video; 19 20 public class ProxyActivity extends Activity 21 { 22 /* 接收mainActivity傳來的*/ 23 ... 24 25 /* classloder來的object*/ 26 ... 27 28 /* 用來加載資源的*/ 29 ... 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) 33 { 34 super.onCreate(savedInstanceState); 35 36 .... 37 } 38 39 /* 加載插件的主activity*/ 40 protected void OpenDefaultActivity() 41 { 42 ... 43 } 44 45 /* 加載插件的指定activity*/ 46 @SuppressLint("NewApi") protected void OpenAppointActivity(final String className) 47 { 48 ... 49 } 50 51 52 protected void loadResources() 53 { 54 ... 55 } 56 57 /* 重寫這兩個加載資源的函數 */ 58 .... 59 60 61 /* 反射其餘生命週期函數 */ 62 @Override 63 protected void onStart() { 64 super.onStart(); 65 ReflectOnFunction("onStart"); 66 } 67 68 @Override 69 protected void onResume() { 70 super.onResume(); 71 ReflectOnFunction("onResume"); 72 } 73 74 @Override 75 protected void onPause() { 76 super.onPause(); 77 ReflectOnFunction("onPause"); 78 } 79 80 @Override 81 protected void onStop() { 82 super.onStop(); 83 ReflectOnFunction("onStop"); 84 } 85 86 @Override 87 protected void onDestroy() { 88 super.onDestroy(); 89 ReflectOnFunction("onDestroy"); 90 } 91 92 private void ReflectOnFunction(String FunctionName) 93 { 94 Method onFunction; 95 try 96 { 97 onFunction = mlocaClass.getDeclaredMethod(FunctionName, new Class[] {}); 98 onFunction.setAccessible(true); 99 onFunction.invoke(mobject); 100 } catch (NoSuchMethodException e) { 101 e.printStackTrace(); 102 } catch (IllegalAccessException e) { 103 e.printStackTrace(); 104 } catch (IllegalArgumentException e) { 105 e.printStackTrace(); 106 } catch (InvocationTargetException e) { 107 e.printStackTrace(); 108 } 109 } 110 }
插件工程中,咱們能夠直接在實際看到的Activity中直接加入反射,修改代碼,也能夠在BaseActivity中進行完成(這裏我選了後者),爲了看起來統一:、佈局
1 package com.bryan.plugin; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.content.res.AssetManager; 6 import android.content.res.Resources; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.view.ViewGroup.LayoutParams; 10 11 public class BaseActivity extends Activity 12 { 13 /* 宿主工程中的代理Activity*/ 14 protected Activity mProxyActivity; 15 16 /* 判斷是被誰調起的,若是是宿主調起的爲1 */ 17 int Who = 0; 18 19 public void setProxy(Activity proxyActivity) 20 { 21 mProxyActivity = proxyActivity; 22 } 23 24 @Override 25 protected void onCreate(Bundle savedInstanceState) 26 { 27 ... 28 } 29 30 ...... 31 32 @Override 33 protected void onResume() { 34 if (mProxyActivity == this) 35 super.onResume(); 36 } 37 38 @Override 39 protected void onPause() { 40 if (mProxyActivity == this) 41 super.onPause(); 42 } 43 44 @Override 45 protected void onStop() { 46 if (mProxyActivity == this) 47 super.onStop(); 48 } 49 50 @Override 51 protected void onDestroy() { 52 if (mProxyActivity == this) 53 super.onDestroy(); 54 } 55 }
插件的實際看到的類中直接重寫這些方法,維持默認的狀態就能夠了:測試
1 package com.bryan.plugin; 2 3 import android.content.Context; 4 import android.graphics.Color; 5 import android.graphics.drawable.BitmapDrawable; 6 import android.os.Bundle; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.view.ViewGroup.LayoutParams; 10 import android.widget.Button; 11 import android.widget.ImageView; 12 import android.widget.LinearLayout; 13 14 public class MainActivity extends BaseActivity { 15 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 20 // 初始化處理佈局 21 InitView(); 22 } 23 24 ..... 25 26 @Override 27 protected void onStart() { 28 super.onStart(); 29 PluginLog.pluginLog("onStart"); 30 } 31 32 @Override 33 protected void onPause() { 34 super.onPause(); 35 PluginLog.pluginLog("onPause"); 36 } 37 38 @Override 39 protected void onResume() { 40 super.onResume(); 41 PluginLog.pluginLog("onResume"); 42 } 43 44 @Override 45 protected void onStop() { 46 super.onStop(); 47 PluginLog.pluginLog("onStop"); 48 } 49 50 @Override 51 protected void onDestroy() { 52 super.onDestroy(); 53 PluginLog.pluginLog("onDestroy"); 54 } 55 }
代碼中的 pluginLog 只是我本身打log用的,沒必要關係它的實現細節。優化
結果this
在宿主程序拉起App後在Logcat中能夠看到:spa
到此爲止,一個相對完整的插件的化的例子就算是作完了,固然這裏面有不少能夠優化的地方,不過我完成這三篇文章的目的也就是對於插件化原理的一個簡單探索,讓想了解插件原理的人入個門。因爲本人是測試,不是開發出身,所以文章內不免會有寫錯誤的地方,但願你們能不吝賜教。