2.0.各种Context创建过程分析

Activity的Context创建过程分析

android应用程序窗口在运行的过程中,需要访问一些特定的资源或者类。这些特定的资源或者类构成了Android应用程序的运行上下文环境,Android应用程序窗口可以通过一个Context接口来访问它,这个Context接口也是我们在开发应用程序时经常碰到的。在本文中,我们就将详细分析Android应用程序窗口的运行上下文环境的创建过程。

 在前面Android应用程序窗口(Activity)实现框架简要介绍和学习计划一文中提到,Android应用程序窗口的运行上下文环境是通过ContextImpl类来描述的,即每一个Activity组件都关联有一个ContextImpl对象。ContextImpl类继承了Context类,它与Activity组件的关系如图1所示:

        这个类图在设计模式里面就可以称为装饰模式。Activity组件通过其父类ContextThemeWrapper和ContextWrapper的成员变量mBase来引用了一个ContextImpl对象,这样,Activity组件以后就可以通过这个ContextImpl对象来执行一些具体的操作,例如,启动Service组件注册广播接收者启动Content Provider组件等操作。同时,ContextImpl类又通过自己的成员变量mOuterContext来引用了与它关联的一个Activity组件,这样,ContextImpl类也可以将一些操作转发给Activity组件来处理。

        在前面Android应用程序启动过程源代码分析一文中,我们已经详细分析过一个Activity组件的启动过程了。在这个启动过程中,最后一步便是通过ActivityThread类的成员函数performLaunchActivity在应用程序进程中创建一个Activity实例,并且为它设置运行上下文环境,即为它创建一个ContextImpl对象。接下来,我们就从ActivityThread类的成员函数performLaunchActivity开始,分析一个Activity实例的创建过程,以便可以从中了解它的运行上下文环境的创建过程,如图2所示:

这个过程一共分为10个步骤,接下来我们就详细分析每一个步骤。

Step 1. ActivityThread.performLaunchActivity

public final class ActivityThread {
    ......
    Instrumentation mInstrumentation;
    ......
    private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
        ComponentName component = r.intent.getComponent();
        ......
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
            ......
        } catch (Exception e) {
            ......
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            ......
            if (activity != null) {
                ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, displayId, r.overrideConfig);
                ......
                appContext.setOuterContext(activity);
                ......
                Configuration config = new Configuration(mConfiguration);
                ......
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstance,
                        r.lastNonConfigurationChildInstances, config);
                ......
                mInstrumentation.callActivityOnCreate(activity, r.state);
                ......  
            }
            ......
        } catch (SuperNotCalledException e) {
            ......
        } catch (Exception e) {
            ......
        }
        return activity;
    }
}

Step 2. Instrumentation.newActivity

class ContextImpl extends Context {  
    ......  
  
    private Context mOuterContext;  
    ......  
  
    ContextImpl() {  
        // For debug only  
        //++sInstanceCount;  
        mOuterContext = this;  
    }  
    ......  
}  

Step 4. new ContextImpl

class ContextImpl extends Context {  
    ......  
  
    private Context mOuterContext;  
    ......  
  
    ContextImpl() {  
        // For debug only  
        //++sInstanceCount;  
        mOuterContext = this;  
    }  
    ......  
}  

Step 5. ContextImpl.setOuterContext

class ContextImpl extends Context {  
    ......  
  
    private Context mOuterContext;  
    ......  
  
    final void setOuterContext(Context context) {  
        mOuterContext = context;  
    }  
  
    ......  
} 

Step 6. Activity.attach

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory, Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
    ......

    private Application mApplication;
    ......

    /*package*/ Configuration mCurrentConfig;
    ......

    private Window mWindow;

    private WindowManager mWindowManager;
    ......

    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);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        ......

        mApplication = application;
        ......

        mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
        ......

        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }
    ......
}

Step 7. ContextThemeWrapper.attachBaseConext

public class ContextThemeWrapper extends ContextWrapper {  
    private Context mBase;  
    ......  
  
    @Override 
    protected void attachBaseContext(Context newBase) {  
        super.attachBaseContext(newBase);  
        mBase = newBase;  
    }  
    ......  
}

Step 8. ContextWrapper.attachBaseConext

public class ContextWrapper extends Context {  
    Context mBase;  
    ......  
  
    protected void attachBaseContext(Context base) {  
        if (mBase != null) {  
            throw new IllegalStateException("Base context already set");  
        }  
        mBase = base;  
    }  
  
    ......  
}

Step 9. Instrumentation.callActivityOnCreate

public class Instrumentation {  
    ......  
  
    public void callActivityOnCreate(Activity activity, Bundle icicle) {  
        ......  
  
        activity.onCreate(icicle);  
  
        ......  
    }  
    ......  
}

Step 10. Activity.onCreate

public class Activity extends ContextThemeWrapper  
        implements LayoutInflater.Factory,  
        Window.Callback, KeyEvent.Callback,  
        OnCreateContextMenuListener, ComponentCallbacks {  
    ......  
  
    boolean mCalled;  
    ......  
  
    /*package*/ boolean mVisibleFromClient = true;  
    ......      
  
    protected void onCreate(Bundle savedInstanceState) {  
        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(  
                com.android.internal.R.styleable.Window_windowNoDisplay, false);  
        mCalled = true;  
    }  
   
    ......  
}

至此,一个Activity组件的创建过程,以及它的运行上下文环境的创建过程,就分析完成了。这个过程比较简单,我们是从中获得以下三点信息:

  1. 一个Android应用窗口的运行上下文环境是使用一个ContextImpl对象来描述的,这个ContextImpl对象会分别保存在Activity类的父类ContextThemeWrapper和ContextWrapper的成员变量mBase中,即ContextThemeWrapper类和ContextWrapper类的成员变量mBase指向的是一个ContextImpl对象。
  2. Activity组件在创建过程中,即在它的成员函数attach被调用的时候,会创建一个PhoneWindow对象,并且保存在成员变量mWindow中,用来描述一个具体的Android应用程序窗口。
  3. Activity组件在创建的最后,即在它的子类所重写的成员函数onCreate中,会调用父类Activity的成员函数setContentView来创建一个Android应用程序窗口的视图。

Service的Context的创建过程分析

ActivityThread.handleCreateService

private void handleCreateService(CreateServiceData data) {
    ...
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }

    try {
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);

        Application app = packageInfo.makeApplication(false, mInstrumentation);
        service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault());
        service.onCreate();
        mServices.put(data.token, service);
        try {
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            // nothing to do.
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
}  

Service.attatch

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;
}

可以看出service和activity的context的创建过程很相似。

Application的Context的创建过程

ActivityThread.handleBindApplication
LoadedApk.makeApplication
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    appContext.setOuterContext(app);

Instrumentation.newApplication(Class<?> clazz, Context context)
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    
Application.attach
final void attach(Context context) {
    attachBaseContext(context);
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

ContextWrapper.attachBaseContext
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

猜你喜欢

转载自www.cnblogs.com/muouren/p/11704777.html
今日推荐