Activity的显示过程

来源:互联网 发布:太平洋战争知乎 编辑:程序博客网 时间:2024/06/15 12:00

上一篇文章提到在ActivityThread会调用performLaunchActivity() 这个函数里面会调用Activity的attach()方法。这个attach就是初始化一些Activity的东西具体代码如下:

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,            NonConfigurationInstances lastNonConfigurationInstances,            Configuration config, String referrer, IVoiceInteractor voiceInteractor,            Window window) {        attachBaseContext(context);        mFragments.attachHost(null /*parent*/);        //得到当前Activity的phoneWindow        mWindow = new PhoneWindow(this, window);        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());            }        }        //把当前Activity的phoneWindow和WindowManager联系起来        mWindow.setWindowManager(                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),                mToken, mComponent.flattenToString(),                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);        if (mParent != null) {            mWindow.setContainer(mParent.getWindow());        }        mWindowManager = mWindow.getWindowManager();        mCurrentConfig = config;    }

代码不多就全部贴出来,说到显示过程我们在attach里面主要关注下面三句
//得到当前Activity的phoneWindow
mWindow = new PhoneWindow(this, window);
//把当前Activity的phoneWindow和WindowManager联系起来
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
这三句就是把phoneWindow(activity的窗口里面包含mDecorView)和windowManager绑定起来,attach就先分析到这里;
我们会在onCreate()调用setContentView(),里面会把对应的view添加到mDecorView里面,执行完onCreate()之后ActivityManagerService会回调onResume(),在回调的过程中

final void handleResumeActivity(IBinder token,            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {        ...            if (r.window == null && !a.mFinished && willBeVisible) {                r.window = r.activity.getWindow();                View decor = r.window.getDecorView();                decor.setVisibility(View.INVISIBLE);                //得到attach里面的 windowManager                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) {                    a.mWindowAdded = true;                    //把decorView添加进来                    wm.addView(decor, l);                }            // If the window has already been added, but during resume            // we started another activity, then don't yet make the            // window visible.            } else if (!willBeVisible) {                if (localLOGV) Slog.v(                    TAG, "Launch " + r + " mStartedActivity set");                r.hideForNow = true;            }            ...                if (r.activity.mVisibleFromClient) {                //把mDecorView显示出来                    r.activity.makeVisible();                }            }            ...        } else {            // If an exception was thrown when trying to resume, then            // just end this activity.            try {                ActivityManagerNative.getDefault()                    .finishActivity(token, Activity.RESULT_CANCELED, null,                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);            } catch (RemoteException ex) {                throw ex.rethrowFromSystemServer();            }        }    }

可以看到activity的显示过程实际就是调用windowManager.addView();

Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,就像(activity的)phoneWindow和popUpWindow 我们设置setContentView来绑定对应的view;
说明View才是Window存在的实体,在实际使用中无法直接访问Window,对Window的访问必须通过WindowManager,比如window的添加过程我们会通过WindowManager.addView(),但是windowManager是一个接口,它具体的实现类是WindowManagerImpl类,但是WindowManagerImpl没有具体实现ViewManager的addView()、updateLayoutView()、removeView(),而是交给WindowManagerGlobal去实现。添加view具体实现步骤如下:
1、检查参数是否合法,如果是子Window那么嗨需要调整一些布局参数
2、创建ViewRootImpl并将View添加到列表
3、通过ViewRootImpl来更新界面并完成Window的添加过程