【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 ...
随机推荐
- div垂直居中 css div盒子上下垂直居中
div垂直居中 css div盒子上下垂直居中,让DIV盒子在任何浏览器中任何分辨率的显示屏浏览器中处于水平居中和上下垂直居中. div垂直居中常用于单个盒子,如一个页面里只有一个登录布局,使用div ...
- Open Xml SDK Word模板开发最佳实践(Best Practice)
1.概述 由于前面的引文已经对Open Xml SDK做了一个简要的介绍. 这次来点实际的——Word模板操作. 从本质上来讲,本文的操作都是基于模板替换思想的,即,我们通过替换Word模板中指定元素 ...
- BZOJ3834 : [Poi2014]Solar Panels
问题相当于找到一个最大的k满足在$[x_1,x_2]$,$[y_1,y_2]$中都有k的倍数 等价于$\frac{x_2}{k}>\frac{x_1-1}{k}$且$\frac{y_2}{k}& ...
- MONO 安装 分析
你是安装在/etc下的吧? 5.2是没有serverbusy的提示的,那时,它就傻等,给人造成down的假像.而现在的版本,会提示的. 你升级时,upgrade后边加参数了吗? 加了 /etc/jw ...
- 命令行安装KVM
查看libvirtd的状态: [root@super67 ~]# /etc/init.d/libvirtd status libvirtd (pid 2503) is running... 安装vn ...
- DirSync: List of attributes that are synced by the Azure Active Directory Sync Tool
http://social.technet.microsoft.com/wiki/contents/articles/19901.dirsync-list-of-attributes-that-are ...
- A trip through the Graphics Pipeline 2011_01
It’s been awhile since I posted something here, and I figured I might use this spot to explain some ...
- DS实验题 sights
算法与数据结构实验题 6.3 sights ★实验任务 美丽的小风姑娘打算去旅游散心,她走进了一座山,发现这座山有 n 个景点, 由于山路难修,所以施工队只修了最少条的路,来保证 n 个景点联通,娇弱 ...
- jQuery 判断表单中多个 input text 中至少有一个不为空
html: 名称1:<input class="seasoning_name" type="text" name="seasoning_name ...
- 嵌入式Linux的FTP服务端软件(stupid-ftpd)
我自己试没成功 http://blog.csdn.net/gzshun/article/details/7358651