红橙Darren视频笔记 界面优化与屏幕适配(上)

1. 内存泄漏,内存溢出与内存抖动

内存泄漏:GC在内存吃紧去回收内存的时候,无法回收某一块不再使用的内存。随着时间的推移会导致内存溢出,一般是强引用导致
之前有总结过内存泄漏的一些case和解决方案
https://blog.csdn.net/u011109881/article/details/61626520
内存溢出:一般会导致程序crash,(out of memory)是由长时间的内存泄漏导致的
内存抖动:GC的频率非常频繁,导致程序再不停的回收和释放内存
比如我们在自定义View中的onDraw开辟大空间或者加载了成百上千条数据的listview没有使用ViewHolder技术,一般会导致内存抖动

2. 自定义View代码在内存方面的优化

第一点是要及时释放资源,第二点是在出现反复调用的地方避免创建新对象(比如for循环中,onDraw中,递归中,循环调用的地方都属于反复调用的case)
举个例子
在之前的课程中,动画讲解 仿58同城 加载动画(https://blog.csdn.net/u011109881/article/details/112167257)
我们写了一个loadComplete方法,现在我们在textView写一个click事件 点击时不断启动MainActivity
这时如果我们启动MainActivity时如果没有调用,loadComplete,动画资源就没有释放
关于第二点,我们原先的代码在startJumpUpAnimate startFullDownAnimate进行循环调用,并且内部还在创建各种属性动画。这里可以有所提升,就是将这些code改成类变量,在自定义View创建的时候就进行一次性初始化,以后复用这些对象就不会导致反复创建对象了。

3. UI渲染与界面卡顿

UI渲染,在一定的时间内必须要测量摆放呈现,

3.1关于卡顿

3.1.1.不断GC的时候会导致界面卡顿(GC会占用主线程)
3.1.2.在主线程中的耗时操作操作

关于第一点:在“2. 自定义View代码在内存方面的优化”中有解决方案,就是减少GC的调用,如何减少?即不要频繁new 大对象(开辟大内存),这样GC就不会频繁调用
关于第二点:
一个解决方案是开辟新线程进行耗时操作,同时为了用户体验,使用进度条。
在此解决方案上,还可以对数据进行部分或全部缓存(部分还是全部取决于数据量),避免用户的每次操作都很耗时。

3.2关于GPU渲染

参考资料
https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering
应用可能会在单个帧内多次绘制同一个像素,这种情况称为“过度绘制”。过度绘制通常是不必要的,最好避免。它会浪费 GPU 时间来渲染与用户在屏幕上所见内容无关的像素,进而导致性能问题。

3.2.1什么是过度绘制

过度绘制是指系统在渲染单个帧的过程中多次在屏幕上绘制某一个像素。例如,如果我们有若干界面卡片堆叠在一起,每张卡片都会遮盖其下面一张卡片的部分内容。
但是,系统仍然需要绘制堆叠中的卡片被遮盖的部分。这是因为堆叠的卡片是根据 Painter 算法(也就是按从后到前的顺序)来渲染的。按照这种渲染顺序,系统可以将适当的透明度混合应用于阴影之类的半透明对象。
注意:过度绘制的问题在 Google I/O 大会性能会议和性能模式视频中讨论过,这个问题现在已没有当时那么严重了。这是因为低端设备的 GPU 性能不断提升,而其显示屏的分辨率保持在了一个相对较低的水平。除非是要针对已知的低性能 GPU 设备进行优化,否则建议将重点放在优化界面线程工作上,以确保应用性能稳定。除此之外,在很多情况下,操作系统优化可以避免应用内的过度绘制(例如,Fragment 背景过度绘制窗口背景)。

3.2.2如何定位过度绘制问题

平台提供了以下工具来帮助您确定过度绘制是否会影响应用的性能。
GPU 过度绘制调试工具
GPU 过度绘制调试工具使用颜色编码来显示应用在屏幕上绘制每个像素的次数。此计数越高,过度绘制影响应用性能的可能性越大。
在这里插入图片描述
有些过度绘制是不可避免的。在优化应用的界面时,应尝试达到大部分显示真彩色或仅有 1 次过度绘制(蓝色)的视觉效果

3.2.3解决过度绘制问题

可以采取以下几种策略来减少甚至消除过度绘制:
移除布局中不需要的背景。
使视图层次结构扁平化。
降低透明度的使用。

3.2.3.1.移除布局中不需要的背景

默认情况下,布局没有背景,这表示布局本身不会直接渲染任何内容。但是,当布局具有背景时,其有可能会导致过度绘制。(因为设置背景GPU会为了背景再次绘制)移除不必要的背景可以快速提高渲染性能。不必要的背景可能永远不可见,因为它会被应用在该视图上绘制的任何其他内容完全覆盖。例如,当系统在父视图上绘制子视图时,可能会完全覆盖父视图的背景。如需查找过度绘制的原因,请在布局检查器工具中浏览层次结构。在浏览过程中,请留意可以移除的背景,因为它们对用户不可见。在许多容器采用同一种背景颜色的情况下,也有机会移除不需要的背景:您可以将窗口背景设置为应用的主背景颜色,并且不为其上面的任何容器定义背景值。

3.2.3.2.使视图层次结构扁平化

借助先进的布局设计方法,您可以轻松对视图进行堆叠和分层,从而打造出精美的设计。但是,这样做会导致过度绘制,从而降低性能,特别是在每个堆叠视图对象都是不透明的情况下,这需要将可见和不可见的像素都绘制到屏幕上。如果遇到这类问题,您可以通过优化视图层次结构来减少重叠界面对象的数量,从而提高性能。如需详细了解如何实现此操作,请参阅优化视图层次结构。(https://developer.android.com/topic/performance/rendering/optimizing-view-hierarchies)
具体的操作方式有以下几种
1.移除多余的嵌套布局
2.采用 merge+include的方式复用布局 而不是直接使用LinearLayout RelativeLayout等布局

    <merge xmlns:android="http://schemas.android.com/apk/res/android">

        <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/add"/>

        <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/delete"/>

    </merge>
    

当你将此布局添加到其他布局中(使用 标记)时,系统会忽略 元素并直接在布局中放置两个按钮,以代替 标记。
3.采用开销较低的布局
例如在 Android 的 N 版本中 ConstraintLayout 类提供了与 RelativeLayout 类似的功能,但开销要低得多

3.2.3.3.降低透明度(减少透明度的使用)

在屏幕上渲染透明像素,即所谓的透明度渲染,是导致过度绘制的重要因素。在普通的过度绘制中,系统会在已绘制的现有像素上绘制不透明的像素,从而将其完全遮盖,与此不同的是,透明对象需要先绘制现有的像素,以便达到正确的混合效果。诸如透明动画、淡出和阴影之类的视觉效果都会涉及某种透明度,因此有可能导致严重的过度绘制。您可以通过减少要渲染的透明对象的数量,来改善这些情况下的过度绘制。例如,如需获得灰色文本,您可以在 TextView 中绘制黑色文本,再为其设置半透明的透明度值。但是,您可以简单地通过用灰色绘制文本来获得同样的效果,而且能够大幅提升性能。
除了过度渲染,我们还可以分析GPU的渲染速度,在哪一个步骤渲染比较耗时,从而有针对性的提高渲染速度。
可以参考https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering#profile_rendering,这里不再展开

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值