关闭

Android GUI系统-ViewTree的遍历(四)

标签: ViewTree的遍历scheduleTraversals
28人阅读 评论(0) 收藏 举报
分类:

那些情况会引起ViewTree的遍历

1)应用程序刚启动时,会在构造出整棵ViewTree后,执行第一次遍历。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) 	@ViewRootImpl.java{
	requestLayout();
}
	

public void requestLayout() @ViewRootImpl.java{
	if (!mHandlingLayoutInLayoutRequest) {
//检查是否是主线程。
		CheckThread();
//表明当前正在发起layout请求。
		mLayoutRequested = true;
//安排一个遍历。
		scheduleTraversals();
	}
}

2requestLayout()@View.javaview对象可以通过调用requestLayout来主动请求遍历。

//当有些什么变化时调用整个方法来刷新view的布局。这会安排一次viewtreelayout传递,但是如果view层级正在执行layout传递不应该调用requestLayout,如果layout正在执行,那么这次请求可能会被放置到当前layout传递的尾部。子类应该重写这个方法。

public void requestLayout() @View.java{
	if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
		ViewRootImpl viewRoot = getViewRootImpl();
//isInLayout()判断当前是否正在进行layout,如果当前正在执行layout,又强制调用了requestLayout ,那么把这个view放在mLayoutRequesters的尾部。
		if (viewRoot != null && viewRoot.isInLayout()) {
			if (!viewRoot.requestLayoutDuringLayout(this)) {
				return;
			}
		}
		mAttachInfo.mViewRequestingLayout = this;
	}

//PFLAG_FORCE_LAYOUT,说明是程序主动请求的layout。
	mPrivateFlags |= PFLAG_FORCE_LAYOUT;
	mPrivateFlags |= PFLAG_INVALIDATED;
//把layout请求提交给它的父类,它的父类可能是ViewGroup,也可能是ViewRoot,最后都要提交到ViewRoot处理,ViewRootImpl中的 requestLayout跟前面提到的应用程序的第一次遍历调用的是同一个函数。
	if (mParent != null && !mParent.isLayoutRequested()) {
		mParent. requestLayout();
	}
}


3setLayoutParams,设置View对象的各种属性。


public void setLayoutParams(ViewGroup.LayoutParams params) @View.java{
//如果父类是ViewGroup,调用 onSetLayoutParams做参数调整, onSetLayoutParams通常是被ViewGroup的子类重写的。
	if (mParent instanceof ViewGroup) {
		((ViewGroup) mParent).onSetLayoutParams(this, params);
	}
//这个调用跟前一个情况一样。
	requestLayout();
}


4invalidate,当前的UI无效了,所以需要重绘。这个方法有多个重载,最后的实现是invalidateInternalinvalidate只能在UI线程调用,其他线程调用postInvalidate()

void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,boolean 	fullInvalidate)@View.java {
//如果view不可见,并且也没有动画在执行,就跳过这次刷新。
	if (skipInvalidate()) {
		return;
	}
//满足以下条件,才可能执行invalidate。
	if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == 
		(PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
		|| (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 				PFLAG_DRAWING_CACHE_VALID)
		|| (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
		|| (fullInvalidate && isOpaque() != mLastIsOpaque)) {
//fullInvalidate是否全面刷新,如果没有明确标记刷新的范围(调用的是有rect参数、或者有r,t,l,b参数的invalidate()方法)
		if (fullInvalidate) {
			mLastIsOpaque = isOpaque();
			mPrivateFlags &= ~PFLAG_DRAWN;
		}

		mPrivateFlags |= PFLAG_DIRTY;

//在不全部刷新的情况下,将需要刷新的区域传递到它的父View。
		final AttachInfo ai = mAttachInfo;
		final ViewParent p = mParent;
		if (p != null && ai != null && l < r && t < b) {
			final Rect damage = ai.mTmpInvalRect;
			damage.set(l, t, r, b);
			p.invalidateChild(this, damage);
		}
	}
}

在调用invalidateChild往上传递时,ViewParent可能是ViewGroup,也可能是ViewRootImpl,但是最终还是要由ViewRootImpl处理,ViewGroupinvalidateChild的处理是从当前点开始,沿着ViewTree回溯收集dirty区域,ViewRootImplinvalidateChild的处理是从ViewTree的根开始,发起ViewTree的遍历。


5setAppVisibility,当应用程序的可见性发生了变化,会调用WMS的这个函数,然后进一步通过WindowState的变量mClientViewRootImplW类型的对象)调用到ViewRootImpldispatchAppVisibilityViewRootImpl收到可见性变化的消息,也会通过scheduleTraversals发起一次遍历。


scheduleTraversalsViewRootImpl中遍历的起点。


void scheduleTraversals() @ViewRootImpl.java{
//当前是不是正在执行遍历。
	if (!mTraversalScheduled) {
		mTraversalScheduled = true;
//向 Choreographer注册了 CALLBACK_TRAVERSAL类型的会调用,一旦有Vsync信号到来,会回调 mTraversalRunnable中的run方法,Vsync是准备UI数据的触发源。
		mChoreographer.postCallback(
			Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
	}
}

TraversalRunnable的run方法,直接调用doTraversal。
void doTraversal()@ViewRootImpl.java {
	if (mTraversalScheduled) {
//把 mTraversalScheduled复位,然后执行遍历 performTraversals。
		mTraversalScheduled = false;
		performTraversals();
	}
}


0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Android View原理(View树遍历,View重绘,View动画)

一、屏幕绘图基础 Android中的GUI系统是客户端和服务端配合的窗口系统,即后台运行了一个绘制服务,每个应用程序都是该服务端的一个客户端,当客户端需要绘制时,首先请求服务端创建一个窗口,然后...
  • wtyvhreal
  • wtyvhreal
  • 2015-04-01 10:36
  • 2847

手机GUI自动化测试介绍(包括android与ios)

手机GUI自动化测试介绍 原文 摘要 众所周知,自动化测试可以一定程度上减轻测试人员负担,提高测试效率,并且通过自动化还可以实现可靠性测试和性能测试。对于移动客户端测试而言,如果我们...
  • mack415858775
  • mack415858775
  • 2014-10-29 17:36
  • 1553

android中 map遍历的四种方式

转自:http://blog.csdn.net/dayanxuqun/article/details/26348277 以下是map遍历的四种方式: // 一、推荐只用value的时候用,都懂...
  • chenguang79
  • chenguang79
  • 2014-12-02 11:01
  • 2708

Android GUI系统-ViewTree的绘图遍历(六)

ViewTree的绘图遍历 绘图遍历也就是ViewTree遍历过程的最后一步。这个过程有3个核心的步骤: 1)canvas= mSurface.lockCanvas(dirty); 2)mVie...
  • lin20044140410
  • lin20044140410
  • 2018-01-07 20:48
  • 22

Android GUI系统-ViewTree的创建(二)

View树的创建过程 当AMS通知应用进程来启动一个Activity任务时,最终这个请求会转化为ActivityThread中的一个消息LAUNCH_ACTIVITY,同类型的消息还是RESUME_...
  • lin20044140410
  • lin20044140410
  • 2017-12-21 22:38
  • 42

Android GUI系统-ViewTree的管理者(三)

作为ViewTree的管理者ViewRoot,是怎么工作的。 一,ViewRootImpl跟WMS间的通信 ViewRootImpl.java在构造的时候,需要建立跟WMS的通信的双向...
  • lin20044140410
  • lin20044140410
  • 2017-12-24 18:16
  • 41

App的启动过程(5)ViewTree遍历中最后一步的Draw

以上是WMS端窗口的添加,下面接着ViewTree遍历中最后一步的Draw的分析。 /* ViewRootImpl.java */ private boolean drawSoftware()à ca...
  • lin20044140410
  • lin20044140410
  • 2017-06-01 17:15
  • 254

Android 7.1 GUI系统-窗口管理WMS-Surface管理(四)

Surface的管理 Surface是窗口能真正显示到物理屏幕上的基础,由surfaceflinger管理,可以通过WindowStateAnimator.java中的变量mDrawState来查看...
  • lin20044140410
  • lin20044140410
  • 2017-12-13 23:27
  • 574

Android图形用户界面开发之ViewTree和DecorView详细介绍

Android图形用户界面开发之ViewTree和DecorView详细介绍 出处:西西整理 作者:西西 日期:2013/1/4 0:23:10 [大 中 小] 评论: 0 | 我要发表看法...
  • murongbingxiao
  • murongbingxiao
  • 2015-07-10 10:09
  • 303

Android图形用户界面开发之ViewTree和DecorView详细介绍

图形用户界面(GUI)是Android应用程序开发不可或缺的一部分。其不仅能为用户提供输入,还能够根据(用户)执行的动作,提供相应的反馈。因此,作为开发人员,能够理解UI(用户界面)是如何创建以及跟新...
  • wxlinwzl
  • wxlinwzl
  • 2014-02-01 23:05
  • 521
    个人资料
    • 访问:35512次
    • 积分:1686
    • 等级:
    • 排名:千里之外
    • 原创:130篇
    • 转载:38篇
    • 译文:0篇
    • 评论:9条
    最新评论