解决Android 高CPU占用率的问题

 更新时间:2023年09月24日 09:29:06   作者:MinQ  
最近测试测试APP的一个功能,发现点击页面上的按钮后,CPU占有率比之前的版本要高,所以本文给大家介绍了如何解决Android 高CPU占用率的问题,需要的朋友可以参考下

背景

最近测试测试APP的一个功能,发现点击页面上的按钮后,CPU占有率比之前的版本要高,达到了4%,之前的版本只有不到1%。由于两个版本之间代码提交特别多,无法直接通过代码变动来对比分析。只好直接通过AS工具profiler来分析应用CPU占用了,看下如何优化。

分析过程

首先从测试同学口中知道了CPU占用出现异常的场景是点击页面上的功能A的按钮。OK,那我们就从点击这个按钮入手。首先打开Profiler,选择对应的APP进程,开始监听当前进程的CPU占用率。

双击CPU一行,我们进入到CPU详情页面,如下:

可以看到在左侧,有4个选项,且下方有record按钮。这里的含义是,我们通过点击record后,profile会开始记录接下来一段时间内,详细的CPU占用信息,记录哪些信息呢,通过上述四个选项供我们选择。

  • Callstack Sample

会显示当前这段时间内,涉及到的进程以及调用栈都有哪些,会精细到进程和具体代码。

  • System Trace

会显示详细的信息,包括VSYNC UI绘制信号,内存占用(不是详细内存占用),各个线程的运行时间和CPU占用。也会精确到代码,但是不会特别详细。适合分析record中等时长的数据。此外这里包含的信息会很多,有助于先手分析。

  • Java/Kotlin Method Trace

内容更详细,会精细到各行代码,但是这个不适合record抓取太长时间的文件,因为AS分析会占用很长时间。

我们先选择SystemTrace,点击Record开始记录信息,我们接着点击功能A按钮,开始复现问题场景,问题复现,点击Stop按钮停止抓取,接着AS会自动解析文件,生成我们详细信息,如下图:

可以看到UI的刷新VSYNC信号刷新很频繁,对应下方主线程代码,存在不少峰值。我们放大下方代码峰值,找到最下方峰顶代码,

可以看到下方在layout中,不停的obtainview,这里有可能是一个列表,ListView或者rectclerview,在不停的更新数据。

我们接着抓一份Java Kotlin Method Trace分析看下:

注意这里要点开:

然后我们随意找到一个峰值,查看其代码源:

这里可以直接直观的看到定位到了我们的代码,LogViewer控件,我们点进去查看源码,会发现里边定义了一个listView。这个ListView的功能是在APP上显示logcat日志,当点击功能A按钮时,会产生大量日志,然后每次需要打印一行日志时候,就会全部更新listView的所有控件,(代码内容不方便粘贴)所以造成APP UI绘制高频率进行,导致CPU的占用率居高。

定位到问题了:ListView不停的刷新UI,导致VSYNC不停的触发绘制,导致CPU占用率高

解决问题

现在我们定位到了问题所在,那么怎么解决呢?

第一步,极端化,直接去掉对应UI

首先我们最直接的方法就是把这个UI直接屏蔽掉,不去初始化以及展示这个UI。

这种处理下,我们看下数据,如图,很明显,VSYNC触发周期长了,UI绘制频率下来了,交给测试一看,CPU占用率降到了1.1%, 直接降了3%。

但是直接去掉这个UI,其实不是很妥,毕竟这样相当于这个UI需求给废了。 我们从ListView代码入手,ListView会产生很多个子View,在我们这个需求中,需要显示logcat日志,意味着,每一行日志都会新生成一个view放入到logcat中,日志越打越多,view对象也越多。不仅UI绘制频繁,内存也会持续上升。所以这里想优化只能减少view的个数,但是,日志内容不能少,个数怎么减呢?比如把所有内容做一个整体,作为一个字符串显示到控件中,但这样就不需要listView了,直接一个TextView即可。我们试下这种方案。

第二步,尝试TextView替换listview实现需求

将布局替换为TextView,通过textView的append属性来实现追加日志内容。可以看到效果出奇的好,VSYNC信号不会很频繁,且没有生成多余的对象。

性能狗测试了一下,CPU占用率为1.7%。

但是TextView也有弊端,对于数据的操作没有listView和recyclerview那么精细化,如果因为业务需求,仍然想用listview怎么办呢?

第三步,尝试优化listView

实际需求中,如果我们绕不开listView,那么就只能想办法去优化它了。从之前的数据来看,是因为UI刷新太频繁,那么我们降低UI的刷新频率呢? 这里改动了一下代码:缓存日志信息,每过500ms才去刷新UI,将缓存的日志显示到listView中,这样改完后,看下效果:

有一些好转,使用性能狗测试下,看看,结果CPU占用率为2.4%,也优化了不少。

总结

对于这种问题,利用好工具profiler对程序进行分析。能够快速找到问题原因的基础在于对工具的熟练程度,对于AS工具的使用,可以直接参考官方文档的介绍:https://developer.android.google.cn/studio/profile/power-profiler?hl=zh-cn

以上就是解决Android 高CPU占用率的问题的详细内容,更多关于Android高CPU占用率的资料请关注脚本之家其它相关文章!

相关文章

  • Android实现支持进度条显示的短信备份工具类

    Android实现支持进度条显示的短信备份工具类

    这篇文章主要介绍了Android实现支持进度条显示的短信备份工具类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • Android拖拽助手ViewDragHelper的创建与使用实例

    Android拖拽助手ViewDragHelper的创建与使用实例

    ViewDragHelper是针对 ViewGroup 中的拖拽和重新定位 views 操作时提供了一系列非常有用的方法和状态追踪,下面这篇文章主要给大家介绍了关于Android拖拽助手ViewDragHelper的创建与使用的相关资料,需要的朋友可以参考下
    2022-05-05
  • Spi机制在Android开发的应用示例详解

    Spi机制在Android开发的应用示例详解

    这篇文章主要为大家介绍了Spi机制在Android开发的应用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Android应用中使用ListView来分页显示刷新的内容

    Android应用中使用ListView来分页显示刷新的内容

    这篇文章主要介绍了Android应用中使用ListView来分页显示刷新的内容的方法,展示了一个点击按钮进行刷新的实例以及下拉刷新分页显示的要点解析,需要的朋友可以参考下
    2016-04-04
  • Android自定义密码输入框和数字键盘

    Android自定义密码输入框和数字键盘

    这篇文章主要为大家详细介绍了Android自定义密码输入框和数字键盘的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Android使用TextView,设置onClick属性无效的解决方法

    Android使用TextView,设置onClick属性无效的解决方法

    下面小编就为大家带来一篇Android使用TextView,设置onClick属性无效的解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • Android NDK开发的环境搭建与简单示例

    Android NDK开发的环境搭建与简单示例

    本文主要介绍Android NDK的知识,这里整理了相关资料,来说明如何搭建相应环境和简单实例,帮助大家理解,有兴趣的小伙伴可以参考下
    2016-09-09
  • android检测网络连接状态示例讲解

    android检测网络连接状态示例讲解

    网络的时候,并不是每次都能连接到网络,因此在程序启动中需要对网络的状态进行判断,如果没有网络则提醒用户进行设置
    2014-02-02
  • kotlin浅析when与循环的使用

    kotlin浅析when与循环的使用

    这篇文章主要介绍了kotlin语言中when与循环的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Android自定义控件实现通用验证码输入框(二)

    Android自定义控件实现通用验证码输入框(二)

    这篇文章主要为大家详细介绍了Android自定义控件实现通用验证码输入框的第二篇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01

最新评论