前言
最近研究了一下安卓的插件化开发框架,查阅了几篇大牛的Blog:
http://blog.csdn.net/singwhatiwanna/article/details/22597587,
膜拜的同时也引发了一些疑问,特在此提出拙见,有不对的地方还请指正。这篇博主给出的插件化开发解决方案是在主应用里使用反射调用本地apk中的activity,使用这种方式调用的activity对象为什么没有activity的特性呢?带着这个问题,我研究了一下activity创建和启动的过程。
android应用程序运行的本质其实是运行dex文件,所以我们能够通过ClassLoader获取apk包里的dex文件,利用反射机制实例化其中的对象。但是通过这种方式调用的activity对象为什么没有activity的特性,这是为什么呢?
Android应用程序的安装过程
首先我们看看一个android应用程序是怎么被安装到手机上的:这篇博客已经做了详细介绍:
http://blog.csdn.net/luoshengyang/article/details/6766010
简单来说,对于第三方应用的安装,首先系统会将apk复制到data/app这个目录下,并且扫描,解压,将解压出来的dex文件放置在data/dalvik-cache这个目录下,并在data/data目录下创建应用的数据目录。解析AndroidManifest.xml文件,提取出所需信息,包括具有intent-filter的四大组件信息(Activity、Service、BroadcastReceiver、ContentProvider)和声明的系统权限等。
Activity的创建和启动
再来看看应用程序的启动:关于Launcher是如何启动应用程序的这里不做介绍,我们只关心activity的创建,初始化和启动过程。
参考文献:http://www.cnblogs.com/bastard/archive/2012/04/07/2436262.html
http://blog.csdn.net/qinjuning/article/details/7310620
实际上,activity和context有着密不可分的关系,context是一个抽象类,它描述的是一个应用程序环境的信息,即上下文,通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作。Context代表了用户和系统的交互过程。侠义理解,获得Context就获得了和系统进行交互的可能性。contextImp是context的实现类,activity既继承了context,并且activity中包含一个指向contextImp的属性。
理解了这些以后,我们再看activity启动的关键代码:android.app.ActivityThread.performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
...
if (activity != null) {
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
...
activity.mCalled = false;
mInstrumentation.callActivityOnCreate(activity, r.state);
...
}
...
}
...
}
实际上activity的初始化,也是通过反射机制构建一个activity对象,看似与我们上面的方法没有什么区别,但是,Activity在创建的时候会new一个ContextImpl对象并在attach方法中关联它,需要注意的是,创建Activity使用的数据结构是ActivityClientRecord,我们在应用层通过反射去启动activity是很难完成系统所做的初始化工作的,所以activity的大部分特性都无法使用。