Window窗口机制——WindowManager,ViewRootImpl,View理解

Android:窗口管理器WindowManager 实际上Android上的窗口指的并不是具体的手机窗口而是一个抽象的概念,它本质上也是一个View,我会把窗口理解成一组有关联的View。与与的关系类似,中方法的实现也是通过远程调用。 阅读详情

在之前的文章中我们说到DecorView在handleResumeActivity方法中被绑定到了WindowManager,也就是调用了windowManager.addView(decorView)。而WindowManager的实现类是WindowManagerImpl,而它则是通过WindowManagerGlobal代理实现addView的,我们来看一下addView()方法

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {

	if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (display == null) {
            throw new IllegalArgumentException("display must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }
        
	final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
	ViewRootImpl root;
    View panelParentView = null;

	root = new ViewRootImpl(view.getContext(), display);
	view.setLayoutParams(wparams);
	mViews.add(view);
	mRoots.add(root);
	mParams.add(wparams);
	//ViewRootImpl开始绘制view
	root.setView(view, wparams, panelParentView);
}

可以看到在WindowManagerGlobal的addView中,最后是调用了ViewRootImpl的setView方法,我们来看一下ViewRootImpl。

ViewRootImpl

ViewRootImpl是一个视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议,作为WindowManagerGlobal中大部分的内部实现,也就说WindowManagerGlobal方法最后还是调用到了ViewRootImpl。

addView,removeView,update调用顺序
WindowManagerImpl -> WindowManagerGlobal -> ViewRootImpl

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {

	requestLayout();

	res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
}

在setView方法中,首先会调用到requestLayout(),表示添加Window之前先完成第一次layout布局过程,以确保在收到任何系统事件后面重新布局。requestLayout最终会调用performTraversals方法来完成View的绘制。

接着会通过WindowSession最终来完成Window的添加过程。在下面的代码中mWindowSession类型是IWindowSession,它是一个Binder对象,真正的实现类是Session,也就是说这其实是一次IPC过程,远程调用了Session中的addToDisPlay方法。

public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
            Rect outOutsets, InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }

这里的mService就是WindowManagerService,也就是说Window的添加请求,最终是通过WindowManagerService来添加的。

View通过ViewRootImpl来绘制

前面说到,ViewRootImpl调用到requestLayout()来完成View的绘制操作:

public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }

View绘制,先判断当前线程,如果不是当前线程则抛出异常,当你在子线程更新UI没使用handler的话就会抛出这个异常。一般在子线程操作UI都会调用到view.invalidate,而View的重绘会触发ViewRootImpl的requestLayout,就会去判断当前线程。

判断完线程后,接着调用scheduleTraversals()。

void scheduleTraversals() {
	if (!mTraversalScheduled) {
		mTraversalScheduled = true;
		mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
	}
}

final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

void doTraversal() {
	performTraversals();
}

private void performTraversals() {  
        ... 
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
        ...
        performLayout(lp, desiredWindowWidth, desiredWindowHeight);
        ...
        performDraw();
        ...
    }
//这几个方法最终都会调用
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);  
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);  
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);  
mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());  
mView.draw(canvas);

performTraversals方法会经过measure、layout和draw三个过程才能将一个View绘制出来,所以View的绘制是ViewRootImpl完成的,另外当手动调用invalidate,postInvalidate,requestLayout最终也会调用performTraversals,来重新绘制View。

View何时被绘制

以SetContentView为例,当Activity的onCreate调用到了setContentView后,view就会被绘制了吗?肯定不是,setContentView只是把需要添加的View的结构添加保存在DecorView中,此时的DecorView还并没有被绘制(没有触发view.measure,layout,draw)。
DecorView真正的绘制显示是在activity.handleResumeActivity方法中DecorView被添加到WindowManager时候,也就是调用到windowManager.addView(decorView)。而在windowManager.addView方法中调用到windowManagerGlobal.addView,开始创建初始化ViewRootImpl,再调用到viewRootImpl.setView,最后是调用到viewRootImpl的performTraversals来进行view的绘制(measure,layout,draw),这个时候View才真正被绘制出来。

这也就是为什么我们在onCreate方法中调用view.getMeasureHeight() = 0的原因,我们知道activity.handleResumeActivity最后调用到的是activity的onResume方法,但是按上面所说在onResume方法中调用就可以得到了吗,答案肯定是否定的,因为ViewRootImpl绘制View并非是同步的,而是异步(Handler)。

而是通过以下方式监听:

view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

    }
});

因为在viewRootImpl的performTraversals的绘制最后,调用了

private void performTraversals() {
	performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
	performLayout(lp, mWidth, mHeight);

	if (triggerGlobalLayoutListener) {
		mAttachInfo.mRecomputeGlobalAttributes = false;
        mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
	}
	performDraw();
}

dispatchOnGlobalLayout会触发OnGlobalLayoutListener的onGlobalLayout()函数回调
但此时View并还没有绘制显示出来,只是先调用了measure和layout,但也可以得到它的宽高了。

public class Window/PhoneWindow(){
	public WindowManager getWindowManager() {
        return mWindowManager;
    }
	
	public final Callback getCallback() {
        return mCallback;
    }

	public final View getDecorView() {
        if (mDecor == null || mForceDecorInstall) {
            installDecor();
        }
        return mDecor;
    }

	private ViewRootImpl getViewRootImpl() {
        if (mDecor != null) {
            ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();
            if (viewRootImpl != null) {
                return viewRootImpl;
            }
        }
        throw new IllegalStateException("view not added");
    }
}
public class Activity(){
	public Window getWindow() {
		//PhoneWindow
        return mWindow;
    }

	public WindowManager getWindowManager() {
		//WindowManagerImpl
        return mWindowManager;
    }
}

public class View(){
	public ViewRootImpl getViewRootImpl() {
        if (mAttachInfo != null) {
            return mAttachInfo.mViewRootImpl;
        }
        return null;
    }

	protected IWindow getWindow() {
        return mAttachInfo != null ? mAttachInfo.mWindow : null;
    }
}

  • 之所以说ViewRootImpl是View和WindowManager的桥梁,是因为在真正操控绘制View的是ViewRootImpl,View通过WindowManager来转接调用ViewRootImpl;
  • 在ViewRootImpl未初始化创建的时候是可以进行子线程更新UI的,而它创建是在activity.handleResumeActivity方法调用,即DecorView被添加到WindowManager的时候;
  • ViewRootImpl绘制View的时候会先检查当前线程是否是主线程,是才能继续绘制下去;
    在这里插入图片描述
Window系列 (一) — WindowManager 详解 WindowManager 详解一、概述二、WindowManager 体系1. 类图2. 源码分析2.1 `ViewManager` 的结构2.2 PhoneWindow 对象何时创建?2.3 WindowManagerImpl 类三、Window 的属性 (类型和显示次序)四、Window 的操作1. Window 的添加过程2. Window 的更新过程3. Window 的删除过程4. I... 阅读详情

相关推荐

Android13 WindowManager addView流程分析

WindowManager的addView方法用户在窗口中添加View,整体流程图:addView方法定义在WindowManager的父类接口ViewManager中,而实现addView方法的则是WindowManagerImpl中,如下所示: WindowManagerGlobal addView 调用WindowManagerGlobal的addView方法: 首先会对参数view、params和display进行检查。注释1处,如果当前窗口要作为子窗口,就会根据父窗口对子窗口的Windo

liuning1985622的博客 1759

WindowManager的一些属性

WindowManager(窗口管理服务),它是显示View的最底层,Toast,Activity,Dialog的底层都有用到了这个WindowManager。WindowManager里面主要是addView,removeView,updateViewLayout这几个方法来显示View,以及通过WindowManager.LayoutParams这个API来设置相关的属性。文章将详细介绍。

Okloong的博客 1433

变焦跟踪理论基础(如何在变焦过程中保持清晰)

如何在整个变焦过程中一直保持图像的清晰度或焦点是变焦跟踪的主要挑战。 当用户在缩放跟踪的情况下改变缩放时,设备保持对焦。 然而,在没有变焦跟踪的情况下,图像变得失焦,图像在变焦跟踪后由于自动对焦(AF)算法才最终对焦。...................................................

ChenYX的博客 20万+

Android源码分析之WindowManager.LayoutParams属性更新过程

1.来源 问题的来源是因为现在的公司准备转向Android,但是又不想放弃原来的系统,所以想把原来在linux上直接跑的系统移植到Android上来,当然一大重头任务就是对原有界面库的移植和Android图形系统的修改。 我们需要对Android的图形系统加以修改,以实现原有系统的图形效果。原来的系统中有一种页面切换效果,需要将它在Android上实现出来。一开始我是在应用程序层面...

473687880 523

matlab生成blocks、bumps和doppler标准测试信号

关键函数:wnoise使用方式X = wnoise(FUN,N) [X,XN] = wnoise(FUN,N,SQRT_SNR) [X,XN] = wnoise(FUN,N,SQRT_SNR,INIT)X = wnoise(FUN,N) 返回由 FUN给出的信号,长度为2^N,幅值范围[0,1].[X,XN] = wnoise(FUN,N,SQRT_SNR) ,返回了一个测试信号X,以及一个加噪

ZSZ_shsf的博客 6579

PDF批量加水印 与 去除水印实践

我们可以给PDF加图片水印或文字水印,要去除图片水印,一般只需要删除最后一个图片对象即可。要去除文字水印,需要保证主体内容和文字水印在/Contents中位于不同的对象内,这样我们只需要删除文字水印对应的对象即可删除水印。而对于主体内容和文字水印已经混合在一个对象时,本文的提供的方法则无能为力,需要进一步深入分析PDF细节。

小小明-代码实体的专栏 2755

Window窗口机制(四)——WindowManager,ViewRootImpl,View理解

在之前的文章中我们说到DecorView在handleResumeActivity方法中被绑定到了WindowManager,也就是调用了windowManager.addView(decorView)。而WindowManager的实现类是WindowManagerImpl,而它则是通过WindowManagerGlobal代理实现addView的,我们来看一下addView()方法。 publ...

Flying snow 2459

人工智能发展史(从起步到磅礴)以及浪潮阶段

随机森林是将多个有差异的弱学习器(决策树)Bagging并行组合,通过建立多个的拟合较好且有差异模型去组合决策,以优化泛化性能的一种集成学习方法。从论文里可以了解到,GPT-1具有1.17个参数,采用了12层的Transformer 解码器结构,使用5GB的无标注文本数据,在8个GPU上训练了一个月,然后再进行人工监督的微调。训练相结合的理念(该方法在当时计算力上还是有很多挑战,基本上都是和链式求导的梯度算法相关的),这也解决了单层感知器不能做非线性分类的问题,开启了神经网络新一轮的高潮。

xiao77224li的博客 7503

理解Window和WindowManager(一)window的添加删除更新view

window表示窗口的概念,平时开发中使用不多,但是某些时候我们需要在桌面上显示一个类似悬浮窗的东西(比如系统弹的吐司:Toast,就是在window上弹得)那么这种效果就需要window来实现。 一、简单介绍 1、window是一个抽象类,他的具体唯一实现类phonewindow 2、创建window使用windowmanager即可,windowmanager是外界访问window的入口...

dev晴天的博客 2690

主流仿真软件Sigrity/HFSS/Siwave/Hyperlynx/ADS差异

在电子设计自动化(EDA)领域,各种仿真软件如Cadence Sigrity、Mentor Graphics的HyperLynx、Keysight的ADS以及ANSYS的SIwave等,都广泛应用于不同的应用场景中。综上所述,这些EDA仿真软件在各自的应用场景中发挥着重要作用,帮助工程师在设计阶段就能够评估和优化电子产品的性能,提高设计的可靠性和效率。:Sigrity由全球最大的EDA公司Cadence推出,Cadence还推出了Orcad和Allegro等著名软件。:由安捷伦(现是德科技)公司开发。

Geektec的专栏 9394

OSCP-Challenge 2 - Relia

使用andrea:PasswordPassword_6登录远程桌面,在c盘根目录下发现一个计划任务的ps,文件,修改执行的exe位木马,获取到milana用户的反弹shell。,发现开放了一个8000端口,但是我们外部是访问不到的,它对应的页面是/var/www/internal/,这个目录下的文件我们是可以访问的,把这个文件打个包放到本地分析下。其中数据的可以直接连接mssql,但是端口是49965,不过在数据库中没发现什么可用的信息,但是可以修改密码直接进后台,这个可以先放放。

羽的博客 7754

Android | 理解Window 和 WindowManager

前言 Window 是一个窗口的概念,是所有视图的载体,不管是 Activity,Dialog,还是 Toast,他们的视图都是附加在 Window 上面的。例如在桌面显示一个悬浮窗,就需要用到 Window 来实现。WindowManager 是访问 Window 的入口。 Window 是一个抽象类,他的实现类是 PhoneWidow,Activity 中的 DecorView ,Dialog 中的 View 都是在 PhoneWindow 中创建的。因此 Window 实际是 View 的直接管理者,

345丶 4397

华为OD机试 - 小扇和小船的数字游戏 - 二进制(Python/JS/C/C++ 2024 C卷 200分)

二进制表示:任何数 n 的二进制表示中,要找到下一个有相同数量的1的数,我们需要在最低位的0后面的最低位的1进行操作。右侧交换法则:找到右侧的第一个0,位于第一个1的左边,将这个0变成1(提升这个位),并将这个1变成0(下移这个位)。调整尾部1:为了得到最小的数,将所有低于已交换的1的位重置,使得所有1尽可能靠右。

学Java,找哪吒 1160

Window和WindowManager和ViewRootImpl

1 Window 1.1什么是Window? Window是一个抽象类,提供了绘制窗口的一组通用API。 Window负责Android中的显示,可以理解为一个View的载体,负责将这个View显示出来。- PhoneWindow是Window的唯一子类。 举例:Activity的mWindow属性就是一个Window对象,它实际是一个PhoneWindow对象,这个对象负责Activity的显示。DecorView是Activity中所有View的根View,因此mWindow对象可以说是DecorV

Catfish_zhy的博客 527

RK3568平台开发系列讲解(安卓篇)LED呼吸灯系统流程

1.app层封装后使用NotificationManager发出:NotificationManager.notify() 2.Android 系统架构中:一个manager类对应一个aidl接口,一个manager对应一个底层的服务,notification也是这个架构

内核笔记 3643

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

理解Window和WIndowManager

Window表示一个窗口的概念,在日常开发中直接接触Window的机会并不多,但是在某些特殊时候我们需要在桌面上显示一个类似悬浮窗的东西,那么这种效果就需要用到Window来实现。Window是一个抽象类,它的具体实现是PhoneWindow。创建一个Window是很简单的事,只需要通过WindowManager即可完成。

m0_73986294的博客 1766

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Android Window学习记录(一)理解window和windowmanager

Android Window学习记录(一)理解window和windowmanager一、Window什么是Window小结为什么需要Window小结Window的相关属性window的type属性Window的flags参数window的solfInputMode属性如何给window属性赋值小结Window和WindowManager的关系二、WindowManagerWindow的添加过程Window的删除过程Window的更新过程参考资料 一、Window 什么是Window 在Android框架层

nous_x的博客 3147

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

理解Window和WindowManager(一)

viewRootImpl的逻辑很多,重要的就是调用了mWindowSession的方法调用了WindowManagerService的方法。mWindowSession是一个IWindowSession类型对象,IWindowSession是一个IBinder接口,他的具体实现类在WindowManagerService,本地的mWindowSession只是一个Binder对象,通过这个mWindowSession就可以直接调用WindowManagerService的方法进行跨进程通信。

m0_61130325的博客 2054

Window和WindowManager深入理解

Window表示一个悬浮窗口,在开发直接接触的并不多,但是当我们需要使用在桌面上显示一个悬浮窗的东西的时候Window就派上用场了。Window是一个抽象类,它的具体实现时PopupWindow类,创建Window很简单,只需要通过WindowManager即可完成。WindowManager是外界访问Window的入口。 Window和WindowManager之间的联系 为了分析Window的...

weixin_43847987的博客 1863

【学习】Android的Window和WindowManager

基本概念 Window表示一个窗口的概念,在日常开发中直接接触的机会不多,但是在某些特殊时候需要在桌面上显示一个类似悬浮窗的东西,就要用到Window实现。它是一个抽象类,具体实现是PhoneWindow。创建一个Window很简单,通过WindowManager即可。WindowManager是外界访问Window的入口,WindowManager和WindowManagerService的交互是一个IPC过程。Android中所有的视图都是通过Window呈现的,不管是Activity、Dialog等,

m0_59162559的博客 3528

Android 理解Window和WindowManager

Android 理解Window和WindowManager Window表示的是一个窗口的概念,它是一个抽象类,具体实现是PhoneWindow。 创建一个Window只需要通过WindowManager即可完成,WindowManager是外界访问Window的入口。Window的具体实现是在WindowManagerService中,WindowManager与WindowManagerSe...

提辖鲁的博客 694

【Android View】窗口机制

Android专题 窗口机制

studyForMokey的博客 1060

06-Window与WindowManager工作原理

*** 窗口类型:应用窗口(1-99)*/// 普通应用窗口// 应用窗口// 启动窗口/*** 窗口类型:子窗口(1000-1999)*/// 面板窗口(如PopupWindow)// 媒体窗口// 子面板窗口// 对话框/*** 窗口类型:系统窗口(2000-2999)*/// 状态栏// 搜索栏// 电话窗口// 系统警告窗口// Toast// 系统悬浮窗// 高优先级电话// 系统对话框// 锁屏对话框// 系统错误// 输入法窗口。

时代我西的博客 962

《Android开发艺术探索》第8章-理解 Window 和 WindowManager 读书笔记

`Window` 表示一个窗口的概念。`Window` 是一个抽象类,它的具体实现是 `PhoneWindow`,同时也是唯一的实现。通过 `WindowManager` 可以创建一个 `Window`。外界访问 `Window` 要通过 `WindowManager`,`Window` 的具体实现位于 `WindowManagerService` 中,`WindowManager` 和 `WindowManagerService` 的交互是一个 IPC 过程。

willwaywang6 1768

理解Window和WindowManager

理解Window和WindowManager一、Window和WindowManager二、Window的内部机制三、Window的创建过程 本篇是个人在阅读安卓开发艺术探索一书后的知识归纳以及分享自己的一些理解所写的博客,在于以后可以方便的进行复习相关知识,毕竟这些基础知识是多多去理解的。 Window简述:Window一个是窗口的概念,一般用来实现悬浮窗的东西。Window是一个抽象类,具体实...

dogofcjiajia的博客 241
上一篇: Android GLSurfaceView模糊效果
下一篇: Android App及Activity回收流程分析
jamespengo
博客等级 码龄16年 83粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值