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下。因此理解这一点对后面的文章阅读相当重要。


此致,敬礼

相关文章
相关标签/搜索