Activity署尤、View、Window之間關(guān)系的分析

看大家都放圖亚侠,我也來一張

通常我們所看到的Activity和View最直觀的關(guān)系是在onCreate()方法中設(shè)置setContentView(LayoutId)曹体,為activity設(shè)置布局文件,這樣view就在界面上顯示出來了硝烂。這個(gè)方法做的操作如下:

 /**
 * Set the activity content from a layout resource.  The resource will be
 * inflated, adding all top-level views to the activity.
 *
 * @param layoutResID Resource ID to be inflated.
 *
 * @see #setContentView(android.view.View)
 * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
 */
public void setContentView(@LayoutRes int layoutResID) {
    //其實(shí)是調(diào)用了window(PhoneWindow)的setContentView方法
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
 }

 public Window getWindow() {
    return mWindow;
 }

activity的setContentView最終調(diào)用的是mWindow的setContentView方法箕别。mWindow的初始化是在activity的attach()方法中做的。

 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) {
          滞谢。串稀。。
    //這里進(jìn)行了初始化狮杨,mWindow的對(duì)象其實(shí)是Window的子類PhoneWindow
    mWindow = new PhoneWindow(this);
    //此處省略n行代碼
    母截。。橄教。清寇。
}

到這里說明了一點(diǎn),activity的setContentView()是調(diào)用了PhoneWindow的setContentView().
接著上PhoneWindow的代碼:

 public void setContentView(int layoutResID) {
    // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
    // decor, when theme attributes and the like are crystalized. Do not check the feature
    // before this happens.
    if (mContentParent == null) {
      //1护蝶、初始化DecorView,生成mContentParent
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    //  這個(gè)先不考慮
    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
    //2华烟、加載activity自己的布局
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
//省略n行代碼
    。持灰。盔夜。。。
}

phoneWindow中的setContentView()方法一共可以分為兩步比吭。第一步:初始化話DectorView 第二步:加載我們自己設(shè)定的布局绽族。到這里加載activity自己的view就結(jié)束了(ps:至于涉及到FrameWork層的東西這里就不作描述了)。主要來看一下installDecor()的操作衩藤。

private void installDecor() {
    if (mDecor == null) {
      //  生成DecorView,一個(gè)繼承了FrameLayout的view
      //private final class DecorView extends FrameLayout implements   RootViewSurfaceTaker {
        mDecor = generateDecor();
        //省略若干代碼
    }
    if (mContentParent == null) {
        //為mContentParent 賦值
        mContentParent = generateLayout(mDecor);
    }
    //省略若干代碼
}
//  生成DecorView
protected DecorView generateDecor() {
    return new DecorView(getContext(), -1);
}

這個(gè)方法里面首先生成了一個(gè)DecorView(繼承了FrameLayout),然后調(diào)用了generateLayout(mDecor)為mContentParent 賦值吧慢。mContentParent 是做什么用的呢?還記得當(dāng)年的夏雨荷嗎赏表?哦 不 是記得phoneWindow中的setContentView()中執(zhí)行的mLayoutInflater.inflate(layoutResID, mContentParent)代碼
嗎检诗。沒錯(cuò),這個(gè)mContentParent就是作為了activity自己的布局(也就是我們自己寫的布局)的一個(gè)父布局而存在瓢剿。

接下來就看一下這個(gè)mContentParent到底是誰吧逢慌。

 protected ViewGroup generateLayout(DecorView decor) {
    //依照慣例 依然是省略n行代碼
    。间狂。攻泼。。
    // Inflate the window decor.

    int layoutResource;
    int features = getLocalFeatures();
    //  根據(jù)不同的features來加載不同的布局
    // System.out.println("Features: 0x" + Integer.toHexString(features));
    if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
        layoutResource = R.layout.screen_swipe_dismiss;
    } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
        if (mIsFloating) {
            TypedValue res = new TypedValue();
            getContext().getTheme().resolveAttribute(
                    R.attr.dialogTitleIconsDecorLayout, res, true);
            layoutResource = res.resourceId;
        } else {
            layoutResource = R.layout.screen_title_icons;
        }
       鉴象。忙菠。。纺弊。牛欢。。
    } else {
        // Embedded, so no decoration is needed.
        layoutResource = R.layout.screen_simple;
        // System.out.println("Simple!");
    }

    mDecor.startChanging();
    //這里 根據(jù)layoutId(上面根據(jù)不同的features 賦值的layoutResource )加載布局
    View in = mLayoutInflater.inflate(layoutResource, null);
    //把加載的布局放入到decorview中
    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) in;

  //public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
  //查找id為ID_ANDROID_CONTENT的控件
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    if (contentParent == null) {
        throw new RuntimeException("Window couldn't find content container view");
    }
淆游。傍睹。。犹菱。
//  返回id為ID_ANDROID_CONTENT的控件
 return contentParent;
}

上面的代碼主要就是完成了加載系統(tǒng)的布局拾稳、把布局放入到dectorview中、查找出com.android.internal.R.id.content的控件已亥。這個(gè)控件就是我們自己寫的布局的父view熊赖。
到這里window、activity虑椎、view之間的關(guān)系就清楚了震鹉。
1、activity的attach方法中執(zhí)行了window的初始化捆姜,window的實(shí)例為PhoneWindow传趾。
2、activity的setContentView(ID)方法最終是調(diào)用的PhoneWindow的setContentView()方法泥技。
3浆兰、PhoneWindow在執(zhí)行setContentView()的過程中生成了一個(gè)frameLayout的子類DecorView.并且根據(jù)feature的類型加載了一個(gè)對(duì)應(yīng)的系統(tǒng)布局,放入了decorview中。系統(tǒng)布局中有一個(gè)id為com.android.internal.R.id.content的framelayout,這個(gè)frameLayout作為一個(gè)父布局加載我們應(yīng)用中自己定義的xml文件簸呈。

也就是說榕订,我們所有看到的頁面其實(shí)都是在window里面的,activity其實(shí)并不直接掌控view而是借助于window展現(xiàn)的view蜕便。下面是時(shí)候放出圖了(這張圖就清楚的展現(xiàn)了activity劫恒、view、window之間的關(guān)系)


1677180-10136019b1f4c254.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末轿腺,一起剝皮案震驚了整個(gè)濱河市两嘴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌族壳,老刑警劉巖憔辫,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異仿荆,居然都是意外死亡贰您,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門赖歌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枉圃,“玉大人,你說我怎么就攤上這事庐冯。” “怎么了坎穿?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵展父,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我棚潦,道長(zhǎng)浪耘,這世上最難降的妖魔是什么拴签? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮吕漂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尘应。我一直安慰自己惶凝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布犬钢。 她就那樣靜靜地躺著苍鲜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玷犹。 梳的紋絲不亂的頭發(fā)上混滔,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼坯屿。 笑死油湖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的领跛。 我是一名探鬼主播乏德,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼隔节!你這毒婦竟也來了鹅经?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤怎诫,失蹤者是張志新(化名)和其女友劉穎瘾晃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幻妓,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦误,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肉津。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片强胰。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妹沙,靈堂內(nèi)的尸體忽然破棺而出偶洋,到底是詐尸還是另有隱情,我是刑警寧澤距糖,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布玄窝,位于F島的核電站,受9級(jí)特大地震影響悍引,放射性物質(zhì)發(fā)生泄漏恩脂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一趣斤、第九天 我趴在偏房一處隱蔽的房頂上張望俩块。 院中可真熱鬧,春花似錦浓领、人聲如沸玉凯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壮啊。三九已至,卻和暖如春撑蒜,著一層夾襖步出監(jiān)牢的瞬間歹啼,已是汗流浹背玄渗。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狸眼,地道東北人藤树。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拓萌,于是被迫代替她去往敵國(guó)和親岁钓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容