zoukankan      html  css  js  c++  java
  • 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;
        }
  • 相关阅读:
    【转】Odoo开发之:工作流 workflow
    【转】Odoo:基本字段类型
    【转】odoo 10的企业微信发送程序介绍
    Installing python-ldap in Ubuntu
    Odoo8中安装新模块找不到的问题
    mybatis缓存
    ThreadPoolExecutor线程池进阶使用
    使用Dubbo实现RPC调用
    java静态代理模式
    java四种线程池
  • 原文地址:https://www.cnblogs.com/muouren/p/11704777.html
Copyright © 2011-2022 走看看