前言


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

实现


  我们直接看实现吧。

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

 package com.bryan.host;

 import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import dalvik.system.DexClassLoader; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.os.Bundle;
import android.provider.MediaStore.Video; public class ProxyActivity extends Activity
{
/* 接收mainActivity传来的*/
... /* classloder来的object*/
... /* 用来加载资源的*/
... @Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState); ....
} /* 加载插件的主activity*/
protected void OpenDefaultActivity()
{
...
} /* 加载插件的指定activity*/
@SuppressLint("NewApi") protected void OpenAppointActivity(final String className)
{
...
} protected void loadResources()
{
...
} /* 重写这两个加载资源的函数 */
.... /* 反射其他生命周期函数 */
@Override
protected void onStart() {
super.onStart();
ReflectOnFunction("onStart");
} @Override
protected void onResume() {
super.onResume();
ReflectOnFunction("onResume");
} @Override
protected void onPause() {
super.onPause();
ReflectOnFunction("onPause");
} @Override
protected void onStop() {
super.onStop();
ReflectOnFunction("onStop");
} @Override
protected void onDestroy() {
super.onDestroy();
ReflectOnFunction("onDestroy");
} private void ReflectOnFunction(String FunctionName)
{
Method onFunction;
try
{
onFunction = mlocaClass.getDeclaredMethod(FunctionName, new Class[] {});
onFunction.setAccessible(true);
onFunction.invoke(mobject);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

  插件工程中,我们可以直接在实际看到的Activity中直接加入反射,修改代码,也可以在BaseActivity中进行完成(这里我选了后者),为了看起来统一:、

 package com.bryan.plugin;

 import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams; public class BaseActivity extends Activity
{
/* 宿主工程中的代理Activity*/
protected Activity mProxyActivity; /* 判断是被谁调起的,如果是宿主调起的为1 */
int Who = 0; public void setProxy(Activity proxyActivity)
{
mProxyActivity = proxyActivity;
} @Override
protected void onCreate(Bundle savedInstanceState)
{
...
} ...... @Override
protected void onResume() {
if (mProxyActivity == this)
super.onResume();
} @Override
protected void onPause() {
if (mProxyActivity == this)
super.onPause();
} @Override
protected void onStop() {
if (mProxyActivity == this)
super.onStop();
} @Override
protected void onDestroy() {
if (mProxyActivity == this)
super.onDestroy();
}
}

  插件的实际看到的类中直接重写这些方法,维持默认的状态就可以了:

 package com.bryan.plugin;

 import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout; public class MainActivity extends BaseActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // 初始化处理布局
InitView();
} ..... @Override
protected void onStart() {
super.onStart();
PluginLog.pluginLog("onStart");
} @Override
protected void onPause() {
super.onPause();
PluginLog.pluginLog("onPause");
} @Override
protected void onResume() {
super.onResume();
PluginLog.pluginLog("onResume");
} @Override
protected void onStop() {
super.onStop();
PluginLog.pluginLog("onStop");
} @Override
protected void onDestroy() {
super.onDestroy();
PluginLog.pluginLog("onDestroy");
}
}

  代码中的 pluginLog 只是我自己打log用的,不必关系它的实现细节。

结果


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

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

  点击下载源代码

【Android开发学习笔记】【高级】【随笔】插件化——Activity生命周期的更多相关文章

  1. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

  2. Android学习路线(十二)Activity生命周期——启动一个Activity

    DEMO下载地址:http://download.csdn.net/detail/sweetvvck/7728735 不像其他的编程模式那样应用是通过main()函数启动的.Android系统通过调用 ...

  3. android 点击返回键 以及 加载activity 生命周期 记录。。。,一目了然

    简叙 Activity 生命周期及android 返回按钮捕捉   @Override protected void onPostCreate(Bundle savedInstanceState) { ...

  4. 【Android开发学习笔记】【高级】【随笔】插件化——资源加载

    前言 上一节我们针对插件最基本的原理进行了一个简单的demo实现,但是由于插件的Context对象被宿主所接管,因此无法加载插件程序的资源.那么如何解决这个问题捏? 有人提出这样的方案:将apk中的资 ...

  5. android开发学习笔记系列(1)-android起航

    前言 在学习安卓的过程中,我觉得非常有必要将自己所学的东西进行整理,因为每每当我知道我应该是如何去实现功能的时候,有许多细节问题我总是会遗漏,因此我也萌生了写一系列博客来描述自己学习的路线,让我的an ...

  6. 【转】Android开发学习笔记(一)——初识Android

    对于一名程序员来说,“自顶向下”虽然是一种最普通不过的分析问题和解决问题的方式,但其却是简单且较为有效的一种.所以,将其应用到Android的学习中来,不至于将自己的冲动演变为一种盲目和不知所措. 根 ...

  7. Android开发学习笔记DDMS的使用

    打开DDMS DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务. DDMS里面包含了:Device(设备) F ...

  8. Android开发学习笔记:浅谈GridView

    GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片等内容,比如实现九宫格图,用GridView是首选,也是最简单的.主要用于设置Adapter. GridView常用的X ...

  9. 【转】Android开发学习笔记:5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

随机推荐

  1. 微信公众账号开发之微信登陆Oauth授权-第一篇

    我曾经在2012年的时候开始研究微信,那时微信的版本还是处于1.0,当时给朋友帮忙做一个基于微信端的web应用,官方的文档是相当少的,百度搜索出来的东西基本也没有多少实用价值,不过是在官网的基础上作了 ...

  2. ural 1306. Sequence Median

    1306. Sequence Median Time limit: 1.0 secondMemory limit: 1 MBLanguage limit: C, C++, Pascal Given a ...

  3. 2015ACM/ICPC亚洲区长春站 J hdu 5536 Chip Factory

    Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  4. ibatis 灵活的配置文件

    <select id="selectAllMmsRepairBySth" parameterClass="hashmap" resultMap=" ...

  5. BZOJ2102 : [Usaco2010 Dec]The Trough Game

    暴力枚举答案然后检验. #include<cstdio> int n,m,i,j,k,a[100],b[100],cnt,ans;char s[20]; int main(){ for(s ...

  6. 【wikioi】1018 单词接龙

    题目链接 算法:DFS+考你阅题 题目描述: 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中 ...

  7. HDNOIP201404最短路径

    HDNOIP201404最短路径 难度级别: A: 编程语言:不限:运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 a.b.c是3个互不相等的1 ...

  8. 给iOS工程增加Daily Build

    给iOS工程增加Daily Build  前言 Daily Build 是一件非常有意义的事情,也是敏捷开发中关于 "持续集成" 的一个实践.Daily Build 对于开发来说有 ...

  9. android之TabHost(上)

    首先建立文件res/layout/tab.xml 代码如下: <?xml version="1.0" encoding="utf-8"?> < ...

  10. CSS3 2D Transform

    在 一个二维或三维空间,元素可以被扭曲.移位或旋转.只不过2D变形工作在X轴和Y轴,也就是大家常说的水平轴和垂直轴:而3D变形工作在X轴和Y轴之外, 还有一个Z轴.这些3D变换不仅可以定义元素的长度和 ...