zoukankan      html  css  js  c++  java
  • 关于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类 路径 frameworksasecorejavaandroidcontentContextWrapper.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;
     
    }
  • 相关阅读:
    Spring中Quartz的配置
    通用表格打印1
    使用Lucene.Net实现全文检索
    DIV CSS 网页兼容全搞定 (IE6 IE7 IE8 IE9 火狐 谷歌)
    Code128 条码生成
    URL参数Base64解密和解密
    JQuery EasyUI 中文API
    linux 下mysql命令 (授权用户 和 基本操作)
    python操作MySQL数据库
    GridView分组,统计,排序的解决方案
  • 原文地址:https://www.cnblogs.com/jiaoxiake/p/7056667.html
Copyright © 2011-2022 走看看