【Android开发学习笔记】【高级】【随笔】插件化——Activity生命周期

前言


  如同第一章我们说的,宿主程序通过 dexclassloader 将插件的类加载进来,然后通过反射去调用它的方法,这样Activity就被当成了一个普通的类来执行了,因此系统不再接管它的生命周期,也就是说Activity的生命周期函数失效了。针对这样的问题,有网友想出使用Fragment来解决此问题,Fragment既有类似于Activity的生命周期,又有类似于View的界面,因此选它比较合适,具体的做法是将Fragment加入到宿主的代理Activity内部,其生命周期将完全由代理Activity来管理,当然采用这种方法的弊端就是:要求apk尽量采用Fragment来实现,并且在页面跳转的时候比较麻烦,因此我们这里就放弃了这个做法,我们依然通过反射的方法来做。 

实现


  我们直接看实现吧。

  首先是在宿主工程的生命周期函数进行反射:

  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用的,不必关系它的实现细节。

结果


   在宿主程序拉起App后在Logcat中可以看到:

  到此为止,一个相对完整的插件的化的例子就算是做完了,当然这里面有很多可以优化的地方,不过我完成这三篇文章的目的也就是对于插件化原理的一个简单探索,让想了解插件原理的人入个门。由于本人是测试,不是开发出身,因此文章内难免会有写错误的地方,希望大家能不吝赐教。

  点击下载源代码

原文地址:https://www.cnblogs.com/by-dream/p/5033696.html