【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 ...
随机推荐
- 分享Kali Linux 2016.2第36周镜像虚拟机
分享Kali Linux 2016.2第36周镜像虚拟机 9月9日,Kali Linux官方发布Kali Linux 2016.2周更新镜像.今天以64位镜像安装了一个虚拟机,分享给大家.该虚拟机 ...
- 记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
题目传送门 /* 记忆化搜索(DP+DFS):dp[i][j] 表示第i到第j个字符,最少要加多少个括号 dp[x][x] = 1 一定要加一个括号:dp[x][y] = 0, x > y; 当 ...
- Viola Jones Face Detector
Viola Jones Face Detector是Paul viola 和 Michael J Jones共同提出的一种人脸检测框架.它极大的提高了人脸检测的速度和准确率. 速度提升方面:利用积分图 ...
- HTMl5/CSS3/Javascript 学习推荐资源
HTMl5/CSS3/Javascript 学习推荐资源 前端的定义应该是数据内容的展示,在国内大家都觉得前端只是HTML+CSS+Javascript,但是实际上与展示有关的都是前端,所以Ruby/ ...
- 【wikioi】1010 过河卒
题目链接 算法:DFS+剪枝 14.01.02 PS: 递推应该也可以的,改天看看 刚开始最容易想到的是朴素搜索 #include <iostream> using namespace s ...
- 【BZOJ】2321: [BeiJing2011集训]星器(数学+特殊的技巧)
http://www.lydsy.com/JudgeOnline/problem.php?id=2321 完全想不到.. 第一眼以为是爆搜,看到数据范围果断放弃:第二眼以为是网络流(因为只有行列操作, ...
- linux下查看一个进程的启动时间和运行时间
使用 ps命令 :#ps -A -opid,stime,etime,args ps -A -opid,stime,etime,args 结果: root:src# ps -A -opid,stime, ...
- Repeater控件中的三目运算
<asp:Repeater ID="rptimg" runat="server"> <ItemTemplate> ...
- 通过ReflectionMethod,我们可以得到Person类的某个方法的信息
PHP反射api由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互.借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传 ...
- Asp.Net:GridView 编辑、删除、自定义分页以后备用
页面 GridView 绑定:在中,有 <asp:BoundField/>和 <asp:TemplateField><ItemTemplate>嵌套服务器控件 &l ...