自定义View从实现到原理(二)- 源码解析Activity的构成

自定义View从实现到原理(二)

View的分发机制在自定义View中属于比较重要的一部分,在这之前,我们有必要了解一下Activity的组成,然后从源码的角度分析View的事件分发机制。

源码解析Activity的构成

我们都知道,点击事件使用MotionEvent来表示的,在一个点击事件发生之后,首先会传到Activity,那么我们首先要了解一下Activity的构成,在我们写Activity的时候,都会用到类似这个语句来加载对应的布局文件:

setContentView(R.layout.activity_app_start);

在setContentView这个方法中,源码有一句我们需要注意:

public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        ****
    }

是由getWindow()这个方法实现的setContentView(),那么这个getWindow()这个方法又代表着什么呢:

public Window getWindow() {
		return mWindow;
	}

可以看到getWindow()这个方法返回了一个Window变量mWindow,继续查看代码找到这个mWindow的赋值在哪里,在Activity的attach()方法中:

mWindow = new PhoneWindow(this);

mWindow被初始化为PhoneWindow,结合上面的

getWindow().setContentView(layoutResID);

这行代码,就可以理解为是Activity的setContentView方法是调用了PhoneWindow类中的setContentWindow()方法,我们来看一下这个方法的关键代码:

if(mContentParent == null){
		installDecor();
	}
	****

看一下installDecor()的方法代码:

if(mDector == null) {
		mDecor = generateDecor();//1
		****
	}
	
if(mContentParent == null){
		mContentParent = generateLayout(mDector);//2
		****
	}	

首先查看1处的代码,generateDector()的代码:

protect DecorView generateDecor() {
		return new DecorView(getContext() , -1);
	}

在这里我们创建了一个DecorView的实例,这个DecorView其实就是Activity中的根View,查看这个DecorView的代码我们可以看出他是PhoneWindow的内部类,并且继承了FrameLayout。

返回上面的代码,我们查看2中generateLayout()方法代码,我们可以知道的是,这个方法的主要作用是根据不同的情况加载不同的布局给layoutResource,类似这样几行代码:

/**
* 几种在源码中加载布局的代码
*/
//1
layoutResource = R.layout.screen_title;

//2
layoutResource = R.layout.screen_title_icons;
****

等等类似这种的代码有多种,我们就看一下第一种 R.layout.screen_title的布局代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:fitsSystemWindows="true">
    <!-- Popout bar for action modes -->
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />
    <FrameLayout
        android:layout_width="match_parent" 
        android:layout_height="?android:attr/windowTitleSize"
        style="?android:attr/windowTitleBackgroundStyle">
        <TextView android:id="@android:id/title" 
            style="?android:attr/windowTitleStyle"
            android:background="@null"
            android:fadingEdge="horizontal"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
    <FrameLayout android:id="@android:id/content"
        android:layout_width="match_parent" 
        android:layout_height="0dip"
        android:layout_weight="1"
        android:foregroundGravity="fill_horizontal|top"
        android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

这个文件在Frameworks,上面的ViewStub是用来显示ActionBar的,下面的两个FrameLayout,一个是用来显示标题title,一个是用来显示内容Content。

经过阅读以上的这些源码,我们梳理一下Activity的组成:
1.Activity中包含setContentView(*)方法,用来加载布局文件;
2.Activity的setContentView()是由一个Window对象实现其自身的setContentView()完成的;
3.这个Window对象本质上来说是一个PhoneWindow对象
4.PhoneWindow对象,设置了Activity的根View:DecorView
5.PhoneWindow中的方法,会根据不同的情况为DecorView进行处理:
如加载了R.layout.screen_title布局,则会将DecorView分成两个区域,一个是Title一个是Content,我们平常所写的布局正是展示在ContentView部分的;

这篇就写到这里,下一篇会开始源码解析View的事件分发机制。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值