canvas教程

用两张图告诉你,为什么你的App会卡顿? 微码农(2)

字号+ 作者:H5之家 来源:H5之家 2017-04-18 18:00 我要评论( )

继续看图。WindowManagerImpl持有了PhoneWindow的引用,因此它可以对PhoneWindow进行管理。同时它还持有一个非常重要的引用mGlobal。这个mGlobal指向一个WindowManagerGlobal类型的单例对象,这个单例每个应用程序

继续看图。WindowManagerImpl持有了PhoneWindow的引用,因此它可以对PhoneWindow进行管理。同时它还持有一个非常重要的引用mGlobal。这个mGlobal指向一个WindowManagerGlobal类型的单例对象,这个单例每个应用程序只有唯一的一个。在图中,我说明了WindowManagerGlobal维护了本应用程序内所有Window的DecorView,以及与每一个DecorView对应关联的ViewRootImpl。这也就是为什么我前面提到过,WindowManager只是一个代理,实际的管理功能是通过WindowManagerGlobal实现的。我们来看个源码的例子就比较清晰了。开始啦!

用两张图告诉你,为什么你的App会卡顿?

image

WimdowManagerImpl.java

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { ... mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); //实际是通过WindowManagerGlobal实现的。 }

从上面的代码可以看出,WindowManagerImpl确实只是WindowManagerGlobal的一个代理而已。同时,上面这个方法在整个Android的视图框架流程中十分的重要。我们知道,在Activity执行onResume()后界面就要开始渲染了。原因是在onResume()时,会调用WindowManager的addView()方法(实际最后调用的是WindowManagerGlobal的addView()方法),把视图添加到窗口上。结合我的这篇【可能是史上最简单的!一张图3分钟让你明白Activity启动流程,不看后悔!】看,可以帮助你更好的理解Android的视图框架。
ActivityThread.java

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { ... ViewManager wm = a.getWindowManager(); //获得WindowManager,实际是WindowManagerImpl ... wm.addView(decor, l); //添加视图 ... wm.updateViewLayout(decor, l); //需要刷新的时候会走这里 ... }

从上面可以看到,当Activity执行onResume()的时候就会添加视图,或者刷新视图。需要解释一点:WindowManager实现了ViewManager接口。

如图中所说,WindowManagerGlobal调用addView()的时候会把DecorView添加到它维护的数组中去,并且会创建另一个关键且极其重要的ViewRootImpl(这个必须要专门讲一下)类型的对象,并且也会把它存到一个数组中维护。
WindowManagerGlobal.java

public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ... root = new ViewRootImpl(view.getContext(), display); //重要角色登场 view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); //保存起来维护 mParams.add(wparams); ... root.setView(view, wparams, panelParentView); //设置必要属性view是DecorView,panelParentView是PhoneWindow ... }

可以看出ViewRootImpl是在Activity执行onResume()的时候才被创建的,并且此时才把DecorView传进去让它管理。

知识点:WindowManager是在onCreate()时被创建。它对窗口的管理能力实际是通过WindowManagerGlobal实现的。在onResume()是视图才通过WindowManager被添加到窗口上。

ViewRootImpl

ViewRootImpl能够和系统的WindowManagerService进行交互,并且管理着DecorView的绘制和窗口状态。非常的重要。赶紧在图中找到对应位置吧!

ViewRootImpl并不是一个View,而是负责管理视图的。它配合系统来完成对一个Window内的视图树的管理。从图中也可以看到,它持有了DecorView的引用,并且视图树它是视图树绘制的起点。因此,ViewRootImpl会稍微复杂一点,需要我们更深入的去了解,在图中我标出了它比较重要的组成Surface和Choreographer等都会在后面提到。

到此,我们已经一起把第一张图撸了一遍了,现在童鞋们因该对Android视图框架有了大致的了解。下面将更进一步的去了解Android的绘制机制。

App总是卡顿到底是什么原因?

下面将会详细的讲解为什么我们设置的视图能够被绘制到屏幕上?这中间究竟隐藏着怎样的离奇?看完之后,你自然就能够从根源知道为什么你的App会那么卡,以及开始有思路着手解决这些卡顿。

用两张图告诉你,为什么你的App会卡顿?

image

同样用一张图来展示这个过程。由于Android绘制机制确实有点复杂,所以第一眼看到的时候你的内心中可能蹦腾了一万只草泥马。不要怕!我们从源头开始,一点一点的梳理这个看似复杂的绘制机制。为什么说看似复杂呢?因为这个过程只需要几分钟。Just Do It!

CPU、GPU是搞什么鬼的?

整天听到CPU、GPU的,你知道他们是干什么的吗?这里简单的提一下,帮助理解后面的内容。

在Android的绘制架构中,CPU主要负责了视图的测量、布局、记录、把内容计算成Polygons多边形或者Texture纹理,而GPU主要负责把Polygons或者Textture进行Rasterization栅格化,这样才能在屏幕上成像。在使用硬件加速后,GPU会分担CPU的计算任务,而CPU会专注处理逻辑,这样减轻CPU的负担,使得整个系统效率更高。

用两张图告诉你,为什么你的App会卡顿?

image

RefreshRate刷新率和FrameRate帧率

RefreshRate刷新率是屏幕每秒刷新的次数,是一个与硬件有关的固定值。在Android平台上,这个值一般为60HZ,即屏幕每秒刷新60次。

FrameRate帧率是每秒绘制的帧数。通常只要帧数和刷新率保持一致,就能够看到流畅的画面。在Android平台,我们应该尽量维持60FPS的帧率。但有时候由于视图的复杂,它们可能就会出现不一致的情况。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 为什么要学习HTML5

    为什么要学习HTML5

    2017-03-26 08:00

  • 为什么使用html5的十大原因!!!

    为什么使用html5的十大原因!!!

    2017-03-19 12:00

  • 用Canvas画图时为什么会闪烁,(只画一条线)

    用Canvas画图时为什么会闪烁,(只画一条线)

    2017-03-09 09:04

  • 为什么要用画图工具来画原型?

    为什么要用画图工具来画原型?

    2017-02-12 14:00

网友点评
)