http://blog.csdn.net/bd_zengxinxin/article/details/52525781

自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因为布局的层次过多,存在不必要的绘制, 或者onDraw等方法中过于耗时。那么究竟需要多快,才能给用户一个流畅的体验呢?那么就需要简单了解下Android的渲染机制:

Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,那么整个过程如果保证在16ms以内就能达到一个流畅的画面。 那么如果操作超过了16ms就会发生下面的情况:

如果系统发生的VSYNC信号,而此时无法进行渲染,还在做别的操作,那么就会导致丢帧的现象, (大家在察觉到APP卡顿的时候,可以看看logcat控制台,会有drop frames类似的警告)。这样的话,绘制就会在下一个16ms的时候才进行绘制, 即使只丢一帧,用户也会发现卡顿的。

那为什么是16ms,16ms意味着着1000/60hz,相当于60fps,那么只要解释为什么是60fps。

这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。12fps大概类似手动快速翻动书籍的帧率, 这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的 效果。 24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。 但是低于30fps是 无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,当然超过60fps是没有必要的。

有了对Android渲染机制基本的认识以后,那么我们的卡顿的原因就在于没有办法在16ms内完成该完成的操作, 而主要因素是在于没有必要的layouts、invalidations、Overdraw。渲染的过程是由CPU与GPU协作完成, 下面一张图很好的展示出了CPU和GPU的工作,以及潜在的问题,检测的工具和解决方案。

我们需要知道: 1.通过Hierarchy Viewer去检测渲染效率,去除不必要的嵌套 2.通过Show GPU Overdraw去检测Overdraw,最终可以通过移除不必要的背景以及使用canvas.clipRect解决大多数问题。

Overdraw

Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面, 如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。

当设计上追求更华丽的视觉效果的时候,我们就容易陷入采用越来越多的层叠组件来实现这种视觉效果的怪圈。这很容易导致大量的性能问题, 为了获得最佳的性能,我们必须尽量减少Overdraw的情况发生。

我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,可以观察UI上的Overdraw情况。

蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。

Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景, 然后里面 的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域, 增加 蓝色区域的占比。这一措施能够显著提升程序性能。

Overdraw 的处理方案一:移除不必要的background

下面看一个简单的展示ListView的例子: activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:background="@android:color/white" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/narrow_space" android:textSize="@dimen/large_text_size" android:layout_marginBottom="@dimen/wide_space" android:text="@string/header_text"/> <ListView android:id="@+id/id_listview_chats" android:layout_width="match_parent" android:background="@android:color/white" android:layout_height="wrap_content" android:divider="@android:color/transparent" android:dividerHeight="@dimen/divider_height"/> </LinearLayout> 

item的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:paddingBottom="@dimen/chat_padding_bottom"> <ImageView android:id="@+id/id_chat_icon" android:layout_width="@dimen/avatar_dimen" android:layout_height="@dimen/avatar_dimen" android:src="@drawable/joanna" android:layout_margin="@dimen/avatar_layout_margin" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/darker_gray" android:orientation="vertical"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/white" android:textColor="#78A" android:orientation="horizontal"> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:padding="@dimen/narrow_space" android:text="@string/hello_world" android:gravity="bottom" android:id="@+id/id_chat_name" /> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:textStyle="italic" android:text="@string/hello_world" android:padding="@dimen/narrow_space" android:id="@+id/id_chat_date" /> </RelativeLayout> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/narrow_space" android:background="@android:color/white" android:text="@string/hello_world" android:id="@+id/id_chat_msg" /> </LinearLayout> </LinearLayout> 

Activity的代码

public class OverDrawActivity01 extends AppCompatActivity { private ListView mListView; private LayoutInflater mInflater ; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_overdraw_01); mInflater = LayoutInflater.from(this); mListView = (ListView) findViewById(R.id.id_listview_chats); mListView.setAdapter(new ArrayAdapter<Droid>(this, -1, Droid.generateDatas()) { @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null ; if(convertView == null) { convertView = mInflater.inflate(R.layout.chat_item,parent,false); holder = new ViewHolder(); holder.icon = (ImageView) convertView.findViewById(R.id.id_chat_icon); holder.name = (TextView) convertView.findViewById(R.id.id_chat_name); holder.date = (TextView) convertView.findViewById(R.id.id_chat_date); holder.msg = (TextView) convertView.findViewById(R.id.id_chat_msg); convertView.setTag(holder); }else { holder = (ViewHolder) convertView.getTag(); } Droid droid = getItem(position); holder.icon.setBackgroundColor(0x44ff0000); holder.icon.setImageResource(droid.imageId); holder.date.setText(

Android渲染机制和丢帧分析相关推荐

  1. Android 中的卡顿丢帧原因概述 - 应用篇

    在Android 中的卡顿丢帧原因概述 - 系统篇[1] 这篇文章中我们列举了系统自身原因导致的手机卡顿问题 , 这一篇文章我们主要列举一些由于 App 自身原因导致的卡顿问题. 各位用户在使用 Ap ...

  2. Android 中的卡顿丢帧原因概述 - 低内存篇

    在Android 中的卡顿丢帧原因概述 - 系统篇 这篇文章中 , 实际案例这里我们有列举一些由于系统低内存导致的卡顿 , 由于 Android 低内存对整机性能影响比较大 , 所以单独写一篇文章 , ...

  3. 用力一瞥Android渲染机制-黄油计划

    一. 渲染基本概念 对于渲染来说在开始前我们先了解几个概念: CPU主要负责包括 Measure,Layout,Record,Execute 的计算操作. GPU主要负责 Rasterization( ...

  4. 深入Android渲染机制

    1.知识储备 CPU: 中央处理器,它集成了运算,缓冲,控制等单元,包括绘图功能.CPU将对象处理为多维图形,纹理(Bitmaps.Drawables等都是一起打包到统一的纹理). GPU:一个类似于 ...

  5. Android Binder机制情景源码分析之Binder回调注册和反注册

    我们在日常开发中,经常用到Binder来进行跨进程通信,有个比较常见的场景是向服务端注册Binder回调,比如: IActivityManager中有两个成对的方法,Client端向AMS所在的服务端 ...

  6. Android Binder机制(1):Binder架构分析

    从这篇博客开始,将进入Binder机制的分析系列,顺序是先讲解Binder机制的框架,理解了整体思想后,再深入分析各层的细节实现,最后会实现一个自己的本地服务. 1.Binder的历史 BeOS是Be ...

  7. Android 渲染机制——SurfaceFlinger

    SurfaceFlinger Android 图形架构使用了生产者--消费者模型.Surface 表示缓冲队列中的生产方,图像流最常见的消耗方是 SurfaceFlinger,该系统服务接收来自于多个 ...

  8. Android UI 渲染机制的演进,你需要了解什么?

    前言 如今UI 渲染可能是诸多性能问题中最容易被察觉到的,Android 开发既要面对各式各样的手机屏幕尺寸和分辨率,还要与"凶残"的产品和 UI 设计师过招. 在正确实现复杂.炫 ...

  9. 理解 Android 消息机制

    本人只是Android小菜一个,写技术文章只是为了总结自己最近学习到的知识,从来不敢为人师,如果里面有不正确的地方请大家尽情指出,谢谢! 本文基于原生 Android 9.0 源码来解析 Androi ...

最新文章

  1. Messaging CorrelationID
  2. thinkphp整合极验滑动验证码源码演示下载
  3. JAVA高精度计算工具
  4. 从linux和ucos的比较中来看进程这个概念
  5. Android 退出应用程序
  6. jQuery系列(十四):jQuery中的ajax
  7. 电视光端机应用范围及故障维护问题介绍
  8. EF ++属性会更新实体
  9. error LNK2019: 无法解析的外部符号 WinMain,该符号在函数 int __cdecl invoke_main(void)”中被引用
  10. html长图转换成pdf,将长 html 导入拆分 PDF
  11. 封装 电流密度 重布线_具有周边硅通孔的晶圆级芯片封装有限元分析
  12. 基于matlab的信号频谱分析 开题报告,基于MATLAB的数字信号处理开题报告
  13. qa 芯片测试_关于半导体设备测试,看这一篇就够了
  14. 台式计算机硬件组装应按什么步骤顺序进行,计算机硬件组装正确步骤
  15. 结算清单html模板,结算清单样本.xls
  16. 量化交易简要入门(一)
  17. 如何使用eclipse开发android
  18. 论文的正确打开方式—如何细读一篇论文分享
  19. Ajax你需要系统的掌握 系统教程
  20. boost------asio库的使用2(Boost程序库完全开发指南)读书笔记

热门文章

  1. python免费试听-Python
  2. python编程小游戏-python趣味入门——写几个常玩的游戏
  3. pythonista安卓版下载-pythonista 3ios
  4. lua学习笔记之函数
  5. codeforces C Deletion of Repeats(hash)
  6. LeetCode Sort Characters By Frequency
  7. 牛客练习赛33 D tokitsukaze and Inverse Number (树状数组求逆序对,结论)
  8. go map的定义和使用 键值对存储
  9. Laravel 事件侦听的几个方法 [Trait, Model boot(), Observer Class]
  10. Oracle day05 索引_数据去重