Android開發之漫漫長途 Ⅲ——Activity的顯示之Window和View(2)

該文章是一個系列文章,是本人在Android開發的漫漫長途上的一點感想和記錄,我會盡可能按照先易後難的順序進行編寫該系列。該系列引用了《Android開發藝術探索》以及《深刻理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相關知識,另外也借鑑了其餘的優質博客,在此向各位大神表示感謝,膜拜!!!另外,本系列文章知識可能須要有必定Android開發基礎和項目經驗的同窗才能更好理解,也就是說該系列文章面向的是Android中高級開發工程師。java


第三篇了,,接着上一篇說 (怎麼感受沒人評論呢) 上一篇咱們只上圖了沒有具體分析,,下面乾貨來了android


先分析setContentView(雖然這個網上一搜處處都是,不過個人不同哦)

仍是先上代碼 activity_main.xml(沒變哦)app

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.helloword.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

MainActivity.java(變了哦)ide

package com.helloword;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //注意咱們先註釋掉該句
        //setContentView(R.layout.activity_main);
    }
}

不是要分析**setContentView(R.layout.activity_main)**爲何註釋掉呢,,先別急,咱們先運行一下,竟然沒有崩潰,只是獲得一個空白內容頁面(這個顯示跟Activity Theme主題設置相關,個人是默認Theme)以下 函數

咱們來看一下View層級圖 佈局

須要注意的地方我用紅色框框圈住了,能夠看到咱們在沒有寫**setContentView(R.layout.activity_main)**的時候,程序依然能夠正常運行,並顯示出Title。並且結合上一篇中 .net

這個圖的話,咱們發現除了紅色區域沒有,其餘區域的都有。那麼該Activity的顯示的基礎——PhoneWindow和頂級View——DecorView是何時建立的呢? 其實該系列的第一篇就提到了一些,在第一篇Android開發之漫漫長途 Ⅰ——Android系統的創世之初以及Activity的生命週期的最後咱們就提到了Activity的建立工做是在android.app.ActivityThread的main函數中完成的。那麼咱們來分析一下該函數(咱們不具體分析源碼,太多了),不過我會上圖 code

好了,接着把**//setContentView(R.layout.activity_main);//去掉。又獲得咱們熟悉的HelloWorld界面,這個界面的層級圖上一篇文章Android開發之漫漫長途 Ⅱ——Activity的顯示之Window和View(1)已經上過了這裏咱們從新上傳一下更詳細的。此次咱們再來看一下這個層級圖是否是理解的更清晰了呢。咱們的setContentView(R.layout.activity_main);內部把activity_main.xml文件解析成View**,並把該View添加到contentVieworm

注:調用setContentView(R.layout.activity_main)和不調用生成DecorView的邏輯是不同的,若是調用了該函數會在該函數內部判斷生成DecorView,若是不調用的話會在handleResumeActivity的時候判斷生成這就是咱們不寫setContentView(R.layout.activity_main),也會生成DecorView的緣由xml


再分析上一篇中的咱們Acitivty代碼

package com.helloword;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        /**
         * 能夠看到咱們熟悉的setContentView(R.layout.activity_main)調用沒有了,
         *而是採用了下面的代碼,運行而後竟然獲得了和setContentView(R.layout.activity_main)
         *的同樣的顯示結果,難道說setContentView(R.layout.activity_main)
         * 邏輯這麼簡單嗎?個人回答是否認的,setContentView(R.layout.activity_main)
         *邏輯並無那麼簡單,不信的話你點擊返回按鈕試試看。(沒法操做了哦,不是大家的手機是否是這樣,反正個人手機點擊返回沒有做用,重寫onBackPressed方法也沒有調用)
         * 
         * (注:我如下面這種方式獲得了和setContentView(R.layout.activity_main)同樣的顯示效果
         *,可這只是爲了分析方便,不要模仿哦    )
         */
         
        //① 解析.activity_main.xml文件並建立View而且指定其父View爲null(即沒有父View)
        View view = getLayoutInflater().inflate(R.layout.activity_main,null);
        //② 設置顯示參數
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                1,
                0,
                PixelFormat.TRANSPARENT);
        //③ 添加View
        getWindowManager().addView(view,params);
    }
}

在分析以前呢,咱們已經把Android Studio 3.0自動生成的MainActivity代碼差很少分析完了,相信各位讀者讀到這裏也對Activiy的啓動有了大體的瞭解。那爲何咱們還要分析咱們本身的代碼呢,由於這對理解ActivityThread.main流程圖的最後一步經過WindowManager添加View有巨大幫助。在咱們的代碼中我直接經過getLayoutInflater().inflate(R.layout.activity_main,null);把xml佈局文件解析成了View,讓後經過 getWindowManager().addView(view,params);添加了View。這不是跟ActivityThread.main流程圖的最後一步經過WindowManager添加View不謀而合了嗎。可是能夠根據咱們代碼獲得的層級圖

能夠看到咱們View的層級圖並無咱們熟悉的PhoneWindow以及DecorView。由於咱們直接使用了WindowManager添加View,addView會新建立一個窗口,就像一個Dialog同樣,並把View加入,除此以外棕色框框圈住的使咱們熟悉的PhoneWindow以及DecorView。所以我十分反對上面的MainActivity寫法哦。Android系統控件自己幫助咱們作了不少事情,咱們使用setContentView(R.layout.activity_main)以前便獲得了一個PhoneWindow以及DecorView,並經過該函數把咱們本身的佈局View放到了DecorView下。因此理解這一點對後面的文章閱讀相當重要。


此致,敬禮

相關文章
相關標籤/搜索