Activity入门(二)

本文深入探讨了Activity的相关类,包括DecorView、ViewRootImpl和WindowManager.LayoutParams之间的关系。通过attach方法启动Activity的过程,以及如何使用startActivity进行跳转。同时,详细阐述了setContentView在布局加载中的作用。

相关类

        与Activity相关的类有很多,彼此之间通过一些变量都可相互引用 如下:

        从上图可以看出,每个Activity实例中都含有一个DecorView对象,ViewRootImpl对象,以及WindowManager.LayoutParams对象()——它是DecorView对应的LayoutParams,三者之间的关联由WMG维护(由于WMI完全委托给了WMG)。

attach()

        除构造函数,该方法是Activity中第一个被执行的方法。该方法内部会初始化一些Activity中的成员变量。如下:
        attachBaseContext(context);//会赋值到mBase成员变量。        
        mWindow = new PhoneWindow(this);
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        mWindowManager = mWindow.getWindowManager();//这里返回的是一个WindowManagerImpl对象
        第一个方法会将传入的context保存到mBase成员变量中。
        从最后两步可以看出,Activity与它所关联的Window对象中的mWindowManager都是指向同一个WindowManageImpl对象。

startActivity()

        所有的startActivity()最终会走到ActivityThread#handleLaunchActivity()。
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //略
        Activity a = performLaunchActivity(r, customIntent);
        //创建Activity实例,并调用到attach(),onCreate(),onStart(),onRestoreInstanceState(),onPostCreate()
        if (a != null) {
            //略
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            //略
        } else {
            //略
        }
    }
performLaunchActivity。其主体代码如下:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }
        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
    //上面是获取待启动activity的信息,并组装成一个ComponentName对象。
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            //略
        } catch (Exception e) {
            //略
        }
    //在newActivity中,是通过反射拿到一个activity的实例对象的,这里就创建了新的activity对象。
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
       //makeApplication 反射拿application对象,如果已经存储就直接返回。并调用Application#onCreate()方法。
            //略
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                //略
                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);
               //略
                if (r.isPersistable()) {//调用到onCreate(),只不过前者调用的是onCreate(Bundle,PersistableBundle),后者调用的是onCreate(Bundle)
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                //略
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();//调用Activity#onStart()
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {//调用onRestoreInstanceState()
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                //由上述两个的判断顺序可以知道,onRestoreInstanceState()是在onStart()之后调用的,并且在有Bundle对象的时候才调用
                if (!r.activity.mFinished) {//调用Activity#onPostCreate()
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    //略
                }
            }
            r.paused = true;
            mActivities.put(r.token, r);
        } //略
        return activity;
    }
        在上述过程中通过createBaseContextForActivity()创建了一个Context对象,方法如下:
    private Context createBaseContextForActivity(ActivityClientRecord r,
            final Activity activity) {
        ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
        appContext.setOuterContext(activity);//这里调用将传入的Activity保存到mOuterContext变量中。
        Context baseContext = appContext;
	//略
        return baseContext;
    }
        我们可以发现在整个过程中,baseContext都是ContextImpl类型的。而该对象会传递到Activity#attach()中,并且最终被赋值到ContextWrapper#mBase(Activity也是间接继承于ContextWrapper)属性。
        而在第四行,将activity传递到了ContextImpl#mOuterContext属性中。因此,在Activity可以通过mBase访问到ContextImpl对象,在ContextImpl中可以通过mOuterContext访问到它关联的Activity对象。
        从这里也可以看到,一个activity就有一个Context。

        经performLaunchActivity()执行完毕之后,得到了一个Activity实例,并调用了attach()->onCreate()->onStart()->onRestoreInstanceState()->onPostCreate()。但并没有调用onResume()
        再回到handleLaunchActivity()中,调用完performLaunchActivity()之后,会调用handleResumeActivity()。如下:
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
        //略
        ActivityClientRecord r = performResumeActivity(token, clearHide);
        if (r != null) {
            final Activity a = r.activity;
            //略
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
                //略
}
        该方法中会调用performResumeActivity(),这里又会调用Activity#performResume(),最终会在这里通过Instrumentation调用onResume()。
        performResumeActivity()执行完毕之后,获取了新建Activity的Window对象(在Activity#attach()中创建)以及DecorView(Activity#onCreate()中调用了setContentView()方法时创建),并将DecorView对象添加到Window中。
        通过WindowManager#addView()内部的一系列执行,最终会对View进行测量、布局和显示。这样整个界面就显示出来了。
整个过程:
        Activity#startActivity()->ActivityThread#handleLaunchActivity()->ActivityThread#performLaunchActivity()->Activity#attach()->Activity#onCreate()到Activity#onPostCreate()的生命周期->ActivityThread#handleResumeActivity()->ActivityThread#performResumeActivity()->Activity#onResume()->WindowManagerImpl#addView()->ViewRootImpl#setView()->ViewRootImpl#requestLayout()->ViewRootImpl#performTraversals()->ViewRootImpl#performMeasure()->ViewRootImpl#performLayout()->ViewRootImpl#performDraw()->Session#addToDisplay()->WindowManagerService#addWindow()到这一步,整个界面才展示出来。
        Activity的创建是在ActivityThread#performLaunchActivity()中完成的。
        与Activity关联的PhoneWindow对象是在Activity#onCreate()中调用setContentView()时完成的,同时也完成了整个xml文件的解析与构建——View树构建完毕,但未measure,layout与draw。
        ViewRootImpl#performMeasure(),performLayout,performDraw():执行view的measure,layout与draw的过程。
        WMS#addWindow()显示整个Window,才显示出具体的布局。

setContentView

        基本上都在PhoneWindow中完成。



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值