FrameLayout measure过程源码Log全解析之四:onMeasure第一部分之ViewGroup对view的管理

从本篇开始,我们会仔细阅读每一句源码,逐行弄清楚代码的详细含义。

本篇会通过getChildCount()讲到ViewGroup在内部如何储存和管理child view。

getChildCount()和mChildCount

先来看第一句

int count = getChildCount();

getChildcount()的定义在ViewGroup类,是mChildrenCount变量的getter方法。

view/ViewGroup.java
public int getChildCount() {
      return mChildrenCount;
}
这个变量的 定义

view/ViewGroup.java
private int mChildrenCount;

初始化是在initViewGroup中,由ViewGroup三个构建函数调用

view/ViewGroup.java
constructor() -> initViewGroup() {
      ...
      mChildrenCount = 0;
      ...
}

 
  

mChildrenCount的值受到以下几个函数的影响,参数简写为(,),下同。

view/ViewGroup.java
 
  
addInArray(,)                // 增加
removeFromArray(,)           // 减少
removeAllViewsInLayout(,)    // 归零

这里的Array是指mChildren,装着所有child view定义为

view/ViewGroup.java
private View[] mChildren;

到此为止我们可能认为getChildCount()返回的是mChildren数列的大小。 但是真的是这样的吗?我们继续看这几个函数

AddInArray代码分析(数字对应图片数字)

1. 在末尾插入view

2. 不在末尾插入view

3. index太大,错误

4. size == count,如果mChildren的长度和mChildCount是一致的话?什么,他们不一致?是的。为了效率,mChildren一次会增加ARRAY_CAPACITY_INCREMENT大小。children变量暂存了之前的mChildren的值,增大mChildren之后,做了拷贝。

5. if分支,和上面一样,只不过分了两次拷贝,中间留出了index的位置以便后面插入。else分支,index之前的值不动,index开始移动到index+1的位置,也是留出index以便插入。

6. 插入view,增大计数。mLastTouchDownIndex是用来debug的,我们主要是读FrameLayout就不深究了。

FrameLayout measure过程源码Log全解析之四:onMeasure第一部分之ViewGroup对view的管理_第1张图片

AddInArray调用分析(数字对应图片数字)
addInArray是私有函数,我们来看看哪些函数会调用它,我们平时写程序的时候,是否也会隐性调用(当然 - _=)

protected attachViewToParent(,)  // view被贴到parent上的时候
public bringChildToFront(,)      // child view交换位置,会有删除和增加
private addViewInner(,)          // 这个是私有函数,我们继续看
而调用addViewInner的函数是

public addView(,)                   // 这个常用到,动态增加view
protected addViewInLayout(,)   // 这个比较少,注释说一般在onLayout里使用,可以不requestLayout,坑。

接下来看第二个函数removeFromArray(,)

private removeFromArray(int index)                // 删除某个位置上的view
private removeFromArray(int start, int count)     // 从某个位置开始,连续删除几个view,范围[start, end)

removeFromArray第一个版本代码分析(数字对应图片数字)
1. mTransitioningViews 是正在动画中的view,如果不是正在动画的话,就删除解除parent view关系,不然留给其他方法处理(endViewTransition)

2. 在末尾就直接删掉,不在末尾做一个拷贝,把index+1位置起的数据前移一格到index位置,如果index超出[0,count)的范围报错。前两者要减少mChildCount。

FrameLayout measure过程源码Log全解析之四:onMeasure第一部分之ViewGroup对view的管理_第2张图片

removeFromArray第二个版本代码分析(数字对应图片数字)

1. 把旧children和count复制一份,确保start和end在合理范围内,如果start就是end不做任何操作,直接返回。

2. 如果删除后半截,逐个解除parent,删除。

3. 如果删除中间半截,先解除这些view的parent,然后把从end开始的部分拷贝到start的位置。然后逐个把后面多出来的部分删除。

4. 把mChildCount减少,注意这里及以上范围都是这里范围是[start, end)

FrameLayout measure过程源码Log全解析之四:onMeasure第一部分之ViewGroup对view的管理_第3张图片

接下来看看那些函数调用了removeFromArray

protected detachViewFromParent(,)    // 有两个版本分别对应删除某个view和删除连续的几个view
public bringChildToFront()           // 见上
private removeViewInternal(,)        // 两个版本,实际进行view的删除工作, 让removeFromArray删除view模型,自己处理动画,焦点等等。不详述。
而removeViewInternal被如下函数调用

public removeView()                  // 删除某个view
public removeViewInLayout()          // layout版本的删除view,坑
public removeViewAt()                // 删除某个index的view
removeAllViewsInLayout

这个比较复杂,打算放到layout系列讲。 
  

总结一下ViewGroup管理child view的方法

FrameLayout measure过程源码Log全解析之四:onMeasure第一部分之ViewGroup对view的管理_第4张图片

----------------------------------------------------------------------------

FrameLayout measure过程源码Log全解析系列


你可能感兴趣的:(FrameLayout measure过程源码Log全解析之四:onMeasure第一部分之ViewGroup对view的管理)