Android -- Activity启动过程中的上下文环境初始化分析

Android -- Activity启动过程中的上下文环境初始化分析


前面简要分析了 AMS启动Activity及应用进程创建的流程,在Activity启动过程中,系统还需要为它准备上下文环境,即“Context”。本次分析,我们就着重分析这部分。


由前面介绍AMS启动Activity中的内容可知,AMS启动Activity时,最终回调用到ActivityThread::handleLaunchActivity()函数,它内部又会调用performLaunchActivity()函数去初始化Activity,并为它设置该Activity运行所需的上下文环境:

private Activity ActivityThread::performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ...
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//首先通过Instrumentation加载这个Activity所在的类,并创建一个它的实例
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            ...
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ...

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);//为该Activity创建ContextImple实例,初始化它的上下文环境
                ...
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window);//Activity::attach()调用

                ...
                r.activity = activity;
                r.stopped = true;//将stopped置为TRUE,在调用onStart()之前,Activity::stopped都是true;
                ...
            }
            r.paused = true;

            mActivities.put(r.token, r);//token实际是指向一个AMS中的ActivityRecord实例,代表当前启动的Activity;将此次ActivityClientRecord对象保存到Map中

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            ...
        }

        return activity;
    }
app对象指向了当前应用的Application对象;下面接着调用函数创建了Context实例,为了更直观的了解Context,我们先看一张Context类家族图谱:




其中ContextImpl类Context模块的真正实现类,它对外提供Context定义的各种业务函数。


接着看createBaseContextForActivity()函数:

    private Context ActivityThread::createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        ...

        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.token, displayId, r.overrideConfig);//传入参数创建ContextImpl实例
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        ...
        return baseContext;
    }
	
	static ContextImpl ContextImpl::createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken, int displayId,
            Configuration overrideConfiguration) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,
                null, overrideConfiguration, displayId);
    }
	
	final void ContextImpl::setOuterContext(Context context) {
        mOuterContext = context;//指向当前的Activity实例
    }
首先根据传入的参数创建ContextImpl实例,并且ContextImpl::mOuterContext实例将指向当前的Activity对象。


最终创建的ContextImpl实例将被返回到performLaunchActivity()函数中以appContext局部变量进行存储,接着就调用Activity::atach()函数,为该Activity绑定、初始化运行时所需的各种组件:

    final void Activity::attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window);//Windwo是抽象类,PhoneWindow是它的子类,实现了它的方法
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);//调用Window.setWindowManager()
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();//WindowManager是接口,获取它的子类实例对象:WindowManagerImpl
        mCurrentConfig = config;
    }
我们关注Context的这一部分,首先调用attachBaseContext()函数将context对象保存到从父类ContextWrapper继承得来的mBase成员中,这块处理较为简单。例如,如果我们在Activity中调用Activity::getApplication()函数,就会返回拥有此Activity的Application实例:

    /** Return the application that owns this activity. */
    public final Application getApplication() {
        return mApplication;
    }

另外,Activity::atach()函数会保存传入的主要参数,如ActivityThread对象、当前应用的Application对象等;由于Activity的主要工作就是与用户交互,此时还会初始化Activity的显示窗口、为其设置窗口管理者等等操作。


至此,Activity有关其Context的设置部分,就分析完成了。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值