蕉下客--)

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

关于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;
}
 
1.在函数newApplication 方法中通过反射调用Appliation类的构造函数。
2.调用Application.attach简历 ContextImp 和 Appliation 对象的关系, 实现如下,
 
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;
 
}

 

posted on 2017-06-20 22:33  蕉下客--)  阅读(489)  评论(0编辑  收藏  举报