关于ContextImp的源码分析
关于ContextImp的源码分析
来源: http://blog.csdn.net/qinjuning/article/details/7310620
Context概述:
Android 开发文档对 Context描述:
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc
大致意思如下:
1、它描述的是一个应用程序环境的信息,即上下文。
2、该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类, 后面我们会讲到是ContextIml类
3、通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Inten 信息等。
我们都知道Activity, Service, Application 类都是都是Context的子类, 类关系图如下:
1. ComtextImp是对抽象类Context 具体实现; ContextImp 有个成员 mOuterContext 类指向所属的ContextWrapper对象
2. ContextWrapper,对Context进行简易的包装(Wrapper),他有一个成员mBase, 这个mBase真正只想的是ContextImp 对象。 通过ContextImp的对象来实现从Context继承来的接口, 这种方式我们成为包装Wrapper. 这个类新增一个接口attachBaseContext, 使用这个方法简历mBase 和ContextImp对象的关系。
3. ContextThemeWrapper 在ContextWrapper基础上增加了Theme方面的接口, 对于Theme接口只有Activity会使用到。 所以Activity继承这个类
4. Service, Application 继承Service类
5、通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类型为LoadedApk)的相关方法而来。ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的所有ContextIml实例,都对应同一个packageInfo对象。
说了这么多,我们还是用源码分析的方式,来阐述我们结论,我们按照以下三个情景对ContextWrapper的子类进行分析。
1.Apliation 对象 和 ContextImp对象的关系建立
2.Service 对象 和 ContextImp对象的关系建立
3.Activity 对象 和 ContextImp对象的关系建立
源码分析:
Context类: /frameworks/base/core/Java/android/content/Context.java
说明: 抽象类,提供了一组通用的API。
public abstract classContext{
...
public abstract Object getSystemService(String name);//获得系统级服务
public abstract void startActivity(Intent intent);//通过一个Intent启动Activity
public abstract ComponentName startService(Intent service);//启动Service
//根据文件名得到SharedPreferences对象
public abstract SharedPreferences getSharedPreferences(String name,int mode);
...
}
ContextIml.java: /frameworks/base/core/java/android/app/ContextImpl.java
说明:该Context类的实现类为ContextIml,该类实现了Context类的功能。请注意,该函数的大部分功能都是直接调用其属性mPackageInfo去完成,这点我们后面会讲到。
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
classContextImpl extends Context{
//所有Application程序公用一个mPackageInfo对象
/*package*/ActivityThread.PackageInfo mPackageInfo;
@Override
publicObject getSystemService(String name){
...
elseif(ACTIVITY_SERVICE.equals(name)){
return getActivityManager();
}
elseif(INPUT_METHOD_SERVICE.equals(name)){
returnInputMethodManager.getInstance(this);
}
}
@Override
publicvoid startActivity(Intent intent){
...
//开始启动一个Activity
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null, null, intent,-1);
}
}
ContextWrapper类 路径 \frameworks\base\core\java\android\content\ContextWrapper.java
说明: 正如其名称一样,该类只是对Context类的一种包装,该类的构造函数包含了一个真正的Context引用,即ContextIml对象。源代码(部分)如下:
publicclassContextWrapper extends Context{
Context mBase;//该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值
//创建Application、Service、Activity,会调用该方法给mBase属性赋值
protectedvoid attachBaseContext(Context base){
if(mBase != null){
thrownewIllegalStateException("Base context already set");
}
mBase = base;
}
@Override
publicvoid startActivity(Intent intent){
mBase.startActivity(intent);//调用mBase实例方法
}
}
ContextThemeWrapper类 路径:/frameworks/base/core/java/android/view/ContextThemeWrapper.java
说明:该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。只有Activity需要主题,Service不需要主题,所以Service直接继承于ContextWrapper类。源代码(部分)如下:
public classContextThemeWrapper extends ContextWrapper{
//该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值
privateContext mBase;
//mBase赋值方式同样有一下两种
publicContextThemeWrapper(Context base,int themeres){
super(base);
mBase = base;
mThemeResource = themeres;
}
@Override
protectedvoid attachBaseContext(Context newBase){
super.attachBaseContext(newBase);
mBase = newBase;
}
}
Activity类 、Service类 、Application类本质上都是Context子类, 更多信息大家可以自行参考源代码进行理解。
情景分析一:Apliation对象和ContextImp对象的关系建立
每个应用程序在第一次启动时,都会首先创建Application对象。如果对应用程序启动一个Activity(startActivity)流程比较清楚的话,创建Application的时机在创建handleBindApplication()方法中,该函数位于 ActivityThread.java类
//创建Application时同时创建的ContextIml实例
private final void handleBindApplication(AppBindData data){
...
///创建Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
...
}
publicApplication makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation){
...
try{
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext =newContextImpl();//创建一个ContextImpl对象实例
appContext.init(this, null, mActivityThread);//初始化该ContextIml实例的相关属性
///新建一个Application对象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);//将该Application实例传递给该ContextImpl实例
}
...
}
我们分析创建一个handleBindApplication中核心调用一个函数makeApplication , 在makeApplication中
1. 新建一个ContexImp 的对象,然后对这个类进行初始化
2. 调用Instrumentation.makeApplication 这个方法新建一个应用Appliation 对象app。
3. 调用函数ContexImp.setOuterContext 设置进程上下文的所属对象。
我们进入Instrumentation.makeApplication
publicApplication newApplication(ClassLoader cl,String className,Context context)
throws InstantiationException,IllegalAccessException,
ClassNotFoundException{
return newApplication(cl.loadClass(className), context);
}
/**
* Perform instantiation of the process's {@link Application} object. The
* default implementation provides the normal system behavior.
*
* @param clazz The class used to create an Application object from.
* @param context The context to initialize the application with
*
* @return The newly instantiated Application object.
*/
staticpublicApplication newApplication(Class<?> clazz,Context context)
throws InstantiationException,IllegalAccessException,
ClassNotFoundException{
Application app =(Application)clazz.newInstance();
app.attach(context);
return app;
}
public class Application extends ContextWrapper implements ComponentCallbacks {
/* package */ final void attach(Context context){
attachBaseContext(context);
}
}
情景分析二: Activity对象和ContextImp对象的关系建立
通过startActivity()或startActivityForResult()请求启动一个Activity时,如果系统检测需要新建一个Activity对象时,就会 回调handleLaunchActivity()方法,该方法继而调用performLaunchActivity()方法,去创建一个Activity实例
public final classActivityThread{
....
//创建一个Activity实例时同时创建ContextIml实例
private final void handleLaunchActivity(ActivityRecord r,Intent customIntent){
...
Activity a = performLaunchActivity(r, customIntent);//启动一个Activity
}
private final Activity performLaunchActivity(ActivityRecord r,Intent customIntent){
...
Activity activity = null;
try{
//创建一个Activity对象实例
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
}
if(activity != null){
ContextImpl appContext =newContextImpl();//创建一个Activity实例
appContext.init(r.packageInfo, r.token,this);//初始化该ContextIml实例的相关属性
appContext.setOuterContext(activity);//将该Activity信息传递给该ContextImpl实例
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config =newConfiguration(mConfiguration);
if(DEBUG_CONFIGURATION)
Slog.v(TAG,"Launching activity "+ r.activityInfo.name +" with config "+ config);
activity.attach(appContext,this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config);
...
}
...
}
.....
}
1.通过Instrumention.newAtivity 新建一个Activity对象
2.新建了一个ContextImp 对象, 并且进行初始化。设置Ativity对象为它的所属对象
3、调用Acctivity.attach 函数建Activity 和Context对象的对象关系,代码如下
final void attach(Context context,ActivityThread aThread,
Instrumentation instr,IBinder token,int ident,
Application application,Intent intent,ActivityInfo info,
CharSequence title,Activity parent,String id,
Object lastNonConfigurationInstance,
HashMap<String,Object> lastNonConfigurationChildInstances,
Configuration config){
attachBaseContext(context);
mWindow =PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
.....
}
情景分析三:Apliation对象和ContextImp对象的关系建立
通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 ActivityThread.java类,如下:
//创建一个Service实例时同时创建ContextIml实例
private final void handleCreateService(CreateServiceData data){
...
//创建一个Service实例
Service service = null;
try{
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service =(Service) cl.loadClass(data.info.name).newInstance();
}catch(Exception e){
}
...
ContextImpl context =newContextImpl();//创建一个ContextImpl对象实例
context.init(packageInfo, null,this);//初始化该ContextIml实例的相关属性
//获得我们之前创建的Application对象信息
Application app = packageInfo.makeApplication(false, mInstrumentation);
//将该Service信息传递给该ContextImpl实例
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault());
...
}
1. 通过反射创建一个Service对象
2. 新建了一个ContextImp 对象, 并且进行初始化。设置Servicce对象为它的所属对象
3. 调用Service.attach 函数建立Service和Context对象的对象关系,代码如下
public final void attach(Context context,ActivityThread thread,String className,IBinder token, Application application,Object activityManager){
attachBaseContext(context);
mThread = thread;// NOTE: unused - remove?
mClassName = className;
mToken = token;
mApplication = application;
mActivityManager =(IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
<Build.VERSION_CODES.ECLAIR; }
关于ContextImp的源码分析的更多相关文章
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
- zookeeper源码分析之四服务端(单机)处理请求流程
上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...
- ABP源码分析二:ABP中配置的注册和初始化
一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...
- ABP源码分析三:ABP Module
Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...
随机推荐
- 01_13_JSP编译指令
01_13_JSP编译指令 1. Directive Directive(编译指令)相当于在编译期间的命令 格式: <%@Directive 属性=”属性值”%> 常见的Directive ...
- 梁勇Java语言程序设计第三章全部例题 为第五次作业
完成例题3-1,通过系统当前时间毫秒值获取随机10以内的整数判断加的结果是否正确,不用if语句 package com.swift; import java.util.Scanner; public ...
- Oracle数据库学习(四)
11.创建表 crate table tab1(f_id number not null,f_a varchar2(7) not null,f_b number(6,2) not null): 主键: ...
- Linux入门-第七周
1.编写脚本实现传入进程PID,查看对应进程/proc下CPU.内存指标. #!/bin/bash read -p "Input PID Value: " pid #读取PID进程 ...
- 工具之UltraEdit之正则表达式
- 【CodeBase】PHP立即输出结果
利用ob_flush输出缓冲区内容 /* *Author:YunGaZeon *usage:streamout($str) */ function streamout($str) { echo str ...
- vue 组件的书写
简单的来说是 vue组件最核心的就是props和自定义函数,来实现组件的开发 最简单的一个组件 子组件如下: <template> <div class="bgClass& ...
- tcl之关于TCL
- CSU 1997-Seating Arrangement
Seating Arrangement Mr. Teacher老师班上一共有n个同学,编号为1到n. 在上课的时候Mr. Teacher要求同学们从左至右按1, 2, -, n的顺序坐成一排,这样每个 ...
- HOJ_14001 Just Terraffic!
题意相对来说比较扭曲..所以来说下模型,具体做法有兴趣的孩纸去问度娘或者波塞冬吧~~ 给出一个序列长度,并且输入该序列,该序列的含义是横坐标: 任何两个相邻坐标绝对值小于等于1000的必然为一个整体, ...