【Android开发学习笔记】【高级】【随笔】插件化——Activity生命周期
前言
如同第一章我们说的,宿主程序通过 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生命周期的更多相关文章
- android开发学习笔记000
使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...
- Android学习路线(十二)Activity生命周期——启动一个Activity
DEMO下载地址:http://download.csdn.net/detail/sweetvvck/7728735 不像其他的编程模式那样应用是通过main()函数启动的.Android系统通过调用 ...
- android 点击返回键 以及 加载activity 生命周期 记录。。。,一目了然
简叙 Activity 生命周期及android 返回按钮捕捉 @Override protected void onPostCreate(Bundle savedInstanceState) { ...
- 【Android开发学习笔记】【高级】【随笔】插件化——资源加载
前言 上一节我们针对插件最基本的原理进行了一个简单的demo实现,但是由于插件的Context对象被宿主所接管,因此无法加载插件程序的资源.那么如何解决这个问题捏? 有人提出这样的方案:将apk中的资 ...
- android开发学习笔记系列(1)-android起航
前言 在学习安卓的过程中,我觉得非常有必要将自己所学的东西进行整理,因为每每当我知道我应该是如何去实现功能的时候,有许多细节问题我总是会遗漏,因此我也萌生了写一系列博客来描述自己学习的路线,让我的an ...
- 【转】Android开发学习笔记(一)——初识Android
对于一名程序员来说,“自顶向下”虽然是一种最普通不过的分析问题和解决问题的方式,但其却是简单且较为有效的一种.所以,将其应用到Android的学习中来,不至于将自己的冲动演变为一种盲目和不知所措. 根 ...
- Android开发学习笔记DDMS的使用
打开DDMS DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务. DDMS里面包含了:Device(设备) F ...
- Android开发学习笔记:浅谈GridView
GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片等内容,比如实现九宫格图,用GridView是首选,也是最简单的.主要用于设置Adapter. GridView常用的X ...
- 【转】Android开发学习笔记:5大布局方式详解
Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...
随机推荐
- HealthKit开发快速入门教程之HealthKit数据的操作
HealthKit开发快速入门教程之HealthKit数据的操作 数据的表示 在HealthKit中,数据是最核心的元素.通过分析数据,人们可以看到相关的健康信息.例如,通过统计步数数据,人们可以知道 ...
- 大白话strom——问题收集(持续更新ing)
本文导读: 1.基于storm的应用 2.storm的单点故障解决 3.strom与算法的结合学习4.杂记——常见问题的解答5.http://www.blogchong.com/catalog.asp ...
- 用java删除文件夹里的所有文件
import java.io.File; public class Test { public static void main(String args[]){ Test t = new Test() ...
- QDialog, QFileDialog 和 QDesktopServices 的使用方法
Qt中的QDialog类是用来生成对话框的类,QFileDialog 类是QDialog的衍生类,主要用来生成打开文件,或是打开文件目录的对话框,或者是保存文件的对话框,下面我们一一来看代码: 1. ...
- 移动web app开发小贴士 收藏有用
1 创建主屏幕图标 (Creating a home screen icon ,for ios) 1 2 3 4 5 6 //57*57 <link rel="apple-touc ...
- serv-u and hway3.0
一个非常好用的su提权脚本,在支持php的环境下,目录可读可写,基本秒杀. <? //HWay && Serv-U by r00t //r00t@007team.net //ww ...
- lucene 3.0.2 操作进阶
转自:Bannings http://blog.csdn.net/zhangao0086/article/details/ Analyzer(分词器) 分词器能以某种规则对关键字进行分词,将分好的词放 ...
- 如何在64位windows7上同时使用32位和64位的Eclipse
我用的是64位的windows7旗舰版,jdk1.7 64位机器上可以同时运行32位和64位的Eclipse,但是电脑中必须有相应的jdk.Eclipse虽然不需要安装,但是在启动时会检查系统中固定文 ...
- OpenStack手动从数据库中删除实例 - ugyn109的专栏 - 博客频道 - CSDN.NET
由于某种原因我将OpenStack的一个计算节点移除了,但移除前并没有删除在其上运行的实例,后来想通过dash删除这些实例,于是N天过去了,我的dash还显示如下内容:很碍眼是不是?于是我打算手动从数 ...
- mysql外键实战
一.基本概念 1.MySQL中“键”和“索引”的定义相同,所以外键和主键一样也是索引的一种.不同的是MySQL会自动为所有表的主键进行索引,但是外键字段必须由用户 进行明确的索引.用于外键关系的字段必 ...