Android四大组件之Activity

一 简介

本文讲解Activity 与 Window、PhoneWindow、DecorView 之间的关系。

                                                 

 

Window官方文档:Window

public abstract class Window. Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc.

The only existing implementation of this abstract class is android.view.PhoneWindow, which you should instantiate when needing a Window.

释义:每一个 Activity 都持有一个 Window 对象,但是 Window 是一个抽象类,这里 Android 为 Window 提供了唯一的实现类 PhoneWindow。也就是说 Activity 中的 window 实例就是一个 PhoneWindow 对象。

但是 PhoneWindow 终究是 Window,它并不具备多少 View 相关的能力。

不过 PhoneWindow 中持有一个 Android 中非常重要的一个 View 对象 DecorView.

现在的关系就很明确了,每一个 Activity 持有一个 PhoneWindow 的对象,而一个 PhoneWindow 对象持有一个 DecorView 的实例,所以 Activity 中 View 相关的操作其实大都是通过 DecorView 来完成。

二、通过实例讲解三者之间的关系
这里分析一个开发中常见的与 window、decorView 相关的案例——setContentView() 作用原理。

setContentView() 与 DecorView

我们对 Activity 的 setContentView(int resId)方法都非常熟悉,通过该方法,Android 可以帮我们把自己写好的布局文件( resId )最终展示在 Activity 的内容区域中。但具体是怎么做到的呢?

这里其实就是通过不断的传递,把布局文件对应的资源 id 一直传递到这个 Activity 对应的 decorView 中,decorView 本身是一个 FrameLayout,当 decorView 接受到来自 Activity 传递过来的布局 id 后,通过 inflater(布局填充器),把布局资源 id 转换为一个 View,然后把这个布局 View 添加在自身中。

到此为止,我们就在 Activity 中最终看到了自己指定的布局样式。

public void setContentView(int layoutResID) {
  if (mContentParent == null) {
    installDecor();

  } else {
    mContentParent.removeAllViews();

  }

  mLayoutInflater.inflate(layoutResID, mContentParent);

  final Callback cb = getCallback();

  if (cb != null && !isDestroyed()) {
    cb.onContentChanged();

  }

};

这个方法就是最终发生作用的地方,执行完该方法后,从 Activity 传递而来的布局资源 id 最终就会添加到 decorView 中。这里的 installDecor 方法很重要,通过该方法做了很多初始化相关的操作。

总结:其实可以看到上面这个跟 View 操作相关的分析过程中,Activity、以及 Activity 的成员变量 mWindow 什么也没干,他们拿到参数都第一时间都是外抛,最终都会抛给 mWindow 的 decorView 去做具体的逻辑。

这里可能会想,难道 Activity Window 都是傀儡吗?为什么上面的分析中,他们接受到命令后都是一个劲的外抛,自己不处理呢?他们没作用吗?我想其实这里应该是一种特意的设计策略。

作为一个 Activity,它承载了很多功能和使命,它不仅仅是为 View 操作而服务的,所以它把 View 相关的操作交给 DecorView(将指定的R.layout.xxx进行填充
通过布局填充器进行填充) 去完成,通过这种 “外包” 的方式使得自己不用关心 View 操作的细节,到最后其实有点管理中经常说的 “授权” 的意思。

三、布局填充器-LayoutInflater抽象类
(1)上官方文档:LayoutInflater

public abstract class LayoutInflater. Instantiates a layout XML file into its corresponding View objects. It is never used directly. Instead, use getLayoutInflater() or getSystemService(Class) to retrieve a standard LayoutInflater instance that is already hooked up to the current context and correctly configured for the device you are running on.

(2) 在实际开发中LayoutInflater这个类是非常有用的,它的作用类似于findViewById()。不同点是LayoutInflater是用 来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如 Button、TextView等)。 具体作用: ①对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;②对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获取其中的界面元素。

(3)获得 LayoutInflater 实例的三种方式:

①LayoutInflater inflater = getLayoutInflater();

②LayoutInflater localinflater =(LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);

③LayoutInflater inflater = LayoutInflater.from(context);//常用常见

(4)具体实现,以第三种方式为例:

从一个Context中,获得一个布局填充器,这样你就可以使用这个填充器来把xml布局文件转为View对象了,然后通过该对象,可以找到布局中的控件。

//加载布局管理器LayoutInflater inflater = LayoutInflater.from(context);

//将xml布局转换为view对象convertView = inflater.inflate(R.layout.item_myseallist,parent, false);

//利用view对象,找到布局中的组件convertView.findViewById(R.id.delete);

不过实际开发中,可能写的更加简洁一点:参见《第一行代码》RecyclerView

Public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);

    ViewHolder holder = new ViewHolder(view);

    Return holder;

}

即把加载布局管理器和将xml布局转换为view对象合为一步,读者可试着划分两个“.”执行的顺序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步基

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值