Android中级——性能优化

这篇具有很好参考价值的文章主要介绍了Android中级——性能优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

布局优化

UI渲染机制

  • 画面流畅需要帧数为60帧每秒
  • Android通过VSYNC信号触发对UI的绘制,其间隔时间是1000ms/60=16ms(即1000ms内显示60帧画面的单位时间)
  • 故需在16ms之内完成绘制才可以保证画面的流畅
  • 否则会造成丢帧,如一次绘制耗时20ms,当16ms时系统发出VSYNC信号还未绘制完,下一个帧就会被丢弃,直到下次信号才开始绘制,导致16*2ms内都显示同一帧画面(即卡顿)

利用 开发者选项 / Profile GPU Rendering / On srceen as bars 工具可检查UI渲染时间

  • 蓝色:测量绘制Display List的时间
  • 红色:OPenGL渲染Display List所需要的时间
  • 黄色:CPU等待GPU处理的时间
  • 绿色横线:VSYNC时间16ms,需尽量将所有条形图控制在绿线下
    Android中级——性能优化

避免Overdraw

过度绘制会浪费CPU、GPU资源,如系统会默认绘制Activity的背景,若再绘制一个重叠背景则Overdraw了

利用 开发者选项 / Enable GPU Overdraw工具可通过颜色判断Ovedraw的次数,颜色越深表示绘制次数越多

Android中级——性能优化

优化布局层级

对View的测量、布局和绘制都是通过对View树的深度遍历来操作

  • 当布局层级少时,可以使用LinearLayout代替RelativeLayout,前者功能比较简单
  • 当布局层级多时,建议View树的高度不超过10层,可用RelativeLayout替换嵌套的LinearLayout降低高度

利用<include>重用Layout

如下为一个共性的TextView,将宽高设为0可让开发者在使用时对其赋值

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:gravity="center"
    android:textSize="30sp"
    android:text="common ui">
</TextView>

通过include的layout属性引用

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        layout="@layout/common_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

<merge>

如果<include>中的布局和外层布局方向一致

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

   <include layout="@layout/vertical"/>

</LinearLayout>

可以使用<merge>合并,避免多出一个LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="one" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="two" />
</merge>

使用<ViewStub>实现View的延迟加载

如查看的内容只有在点击某个按钮时才会加载、如网络异常界面没必要在界面初始化时加载

  • ViewSub只会在显示时才去渲染布局
  • setVisibility(View.GONE)在初始化布局树的时候就已经添加布局

如下为要加载的view_stub_item.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/img"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/ic_launcher">
</ImageView>

主布局中ViewStub通过layout属性引用布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/vis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="visible" />

    <Button
        android:id="@+id/inflate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="inflate" />

    <ViewStub
        android:id="@+id/viewStub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout="@layout/view_stub_item" />

</LinearLayout>

获取到ViewStub后,可利用setVisibility(View.VISIBLE)或inflate()加载,后者可返回View

public class MainActivity extends AppCompatActivity {

    ViewStub viewStub;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewStub = (ViewStub) findViewById(R.id.viewStub);
        findViewById(R.id.vis).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewStub.setVisibility(View.VISIBLE);
            }
        });
        findViewById(R.id.inflate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                View inflateView = viewStub.inflate();
                ImageView imageView = (ImageView) inflateView.findViewById(R.id.img);
            }
        });
    }
}

Hierarchy View

通过SDK/Tool/monitor.bat,打开Android Device Monitor(打开先需关闭AS),再运行程序,布局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

在Hierarchy View,我们可以看到三层的LinearLayout且没有分支,说明是冗余的

Android中级——性能优化

选择某个View,点击右上角的"Obtain layout time…",可获取布局测量、摆放、绘制的时间,绿黄红颜色表示绘制效率的好中差

Android中级——性能优化

ANR

出现ANR后,会在/data/anr 生成日志文件

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button anr = findViewById(R.id.brn_anr);
        anr.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Toast.makeText(MainActivity.this, "onclick", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

如上,按键事件超过5s未结束,触发ANR,在生成log中可看到是由于线程在Sleeping

Android中级——性能优化
还有一种比较常见的ANR,如下

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button anr = findViewById(R.id.brn_anr);
        anr.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        testANR();
                    }
                }).start();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                initView();
                Log.d(TAG, "onClick: ");
            }
        });
    }

    private synchronized void initView() {

    }

    private synchronized void testANR() {
        try {
            Thread.sleep(30*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

虽然按键事件开启了线程,但调用的方法使用了同一个锁对象,导致后续的initView()方法被阻塞

Android中级——性能优化
如上initView()方法正在等待锁对象MainActivity,其被Thread14持有,再看tid=14的线程,其正在Sleeping

Android中级——性能优化

内存优化

获取内存信息

在开发者模式中找到内存相关信息

Android中级——性能优化

Profiler

可利用AS底部的Profiler实时监控程序的内存使用情况

  • 当内存泄漏时,内存会持续增高
  • 当发生GC时,内存会突然减少

Android中级——性能优化

TraceView

TraceView是一个可视化性能调查工具,用于分析TraceView log,可利用Debug类在onCreate()开启监听,onDestroy()时结束监听

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Debug.startMethodTracing();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Debug.stopMethodTracing();
    }
}

生成的dmtrace.trace存放在以下路径

Android中级——性能优化

此外,还可以通过Android Device Monitor的start method profiling

  • Trace:跟着方法执行的全部过程,资源消耗大
  • Sample:按照指定频率抽样调查,需要较长执行时间获取准备样本

Android中级——性能优化
用Android Device Monitor打开生成的Log,上半部分显示方法执行时间的时间轴,每一行代表一个线程,不同颜色的方块代表下面不同的执行方法

Android中级——性能优化

下半部分为具体方法在所处时间段内的各种类型时间及所占百分比

  • Incl CPU Time——某方法占用的CPU时间
  • Excl CPU Time——某方法本身(不包括子方法)占用的CPU时间
  • Incl Real Time——某方法真正执行时间
  • Excl Real Time——某方法本身(不包括子方法)真正执行时间
  • Calls+RecurCalls——调用次数+递归回调次数

如果Incl CPU Time时间长,但Calls+RecurCalls次数少,则应该优化方法

MAT(Memory Analyzer Tool)

点击Android Device Monitor的Update Heap更新堆数据,在Heap标签点击Cause GC,再点击Dump HPROF File保存文件

Android中级——性能优化

利用Sdk\platform-tools\hprof-conv.exe转换格式

Android中级——性能优化

打开MAT选择Open Dump File

Android中级——性能优化

  • Histogram:查看内存中每个对象的数量、大小和名称
  • Dominator Tree:按照对象大小进行排序,并显示对象之间的引用结构,可找出大对象

dumpsys

dumpsys 可以列出系统相关的信息和服务状态文章来源地址https://www.toymoban.com/news/detail-418851.html

命令 功能
activity Activity栈信息
meminfo 内存信息
procstats 内存状态
package 包信息

到了这里,关于Android中级——性能优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity 性能优化五:渲染模块压力

    Batching 在GPU渲染前,CPU会把数据按batch发送给GPU,每发送一次,都是一个drawcall,GPU在渲染每个batch的时候,会切换渲染状态,这里的渲染状态指的是: 影响对象在屏幕上的外观的渲染属性或材质,比如:材质球,贴如,颜色,渲染模式(透明、半透明)等 unity中的合批方式:

    2024年02月14日
    浏览(38)
  • 性能优化之-更高效的数据渲染

    前言:中心思想还是让请求的资源得到更快响应的方法,比如压缩资源,减少数据量的大小,缓存数据以减少请求数量,http/2让网络传输变得更快这些,下面就让我们来看看浏览器是如何解析这些数据,最终又是如何将他们渲染在屏幕上的?在数据量不变的情况下还有哪些可

    2024年02月09日
    浏览(45)
  • 【Angular性能优化】项目8版本加载速度缓慢、白屏时间、首页渲染性能优化方案

    随着业务的代码一点点增加,加上Angular的项目本身就比 vue、react 的重一些,随之而来的启动速度,更改文件后编译速度,以及打包速度也会变慢,于是乎想着优化下我们的项目。 本文章主要说的是 : 打包Angular项目的一些配置,性能优化方面的方案 打包后,用户进入页面的

    2024年04月10日
    浏览(51)
  • 前端页面渲染多条数据长列表的性能优化

    后端一次性返回了10w条数据,前端该如何处理?长列表性能优化 这个问题其实是考察面试者对性能优化的理解。我们知道,对于大量数据渲染的时候,JS运算并不是性能的瓶颈,性能的瓶颈主要在于渲染阶段,所以页面的卡顿是由于同时渲染大量DOM所引起的。 简单聊一下 s

    2024年02月13日
    浏览(51)
  • 理解React页面渲染原理,如何优化React性能?

    当使用React编写应用程序时,可以使用JSX语法来描述用户界面的结构。JSX是一种类似于HTML的语法,但实际上它是一种JavaScript的扩展,用于定义React元素。React元素描述了我们想要在界面上看到的内容和结构。 在运行React应用程序时,JSX会被转换成真实的DOM元素,这个过程主要

    2024年02月08日
    浏览(46)
  • 极致性能优化:前端SSR渲染利器Qwik.js

    前端性能已成为网站和应用成功的关键要素之一。用户期望快速加载的页面和流畅的交互,而前端框架的选择对于实现这些目标至关重要。然而,传统的前端框架在某些情况下可能面临性能挑战且存在技术壁垒。 在这个充满挑战的背景下,我们引入了 Qwik.js 框架。Qwik.js 不仅

    2024年02月05日
    浏览(67)
  • 解决前端性能问题:如何优化大量数据渲染和复杂交互?

    ✨✨祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心!✨✨  🎈🎈作者主页: 喔的嘛呀🎈🎈 目录 引言 一、分页加载数据 二、虚拟滚动 三、懒加载 四、数据缓存 五、减少重绘和回流 六、优化图片和资源: 七、合并压缩文件 八、使用Web Workers  在前端开发

    2024年03月10日
    浏览(65)
  • 【前端八股文】浏览器系列:性能优化——HTML、CSS、JS、渲染优化

    本系列目录:【前端八股文】目录总结 是以《代码随想录》八股文为主的笔记。详情参考在文末。 代码随想录的博客_CSDN博客-leecode题解,ACM题目讲解,代码随想录领域博主 性能优化,从以下几个方面来进行。 避免HTML中直接写CSS viewport加速页面渲染 使用语义化标签 减少标签的

    2023年04月20日
    浏览(61)
  • 【Qt 性能优化】 理解与优化Qt信号槽机制 - 提升应用性能的关键策略

    在这个科技日新月异的时代,软件开发不仅仅是编写代码,更是一种艺术。正如著名计算机科学家 Edsger Dijkstra 所说:“计算机科学并不仅仅关于机器,而是更多地关于人的智慧。” Qt框架,作为一个深受广大开发者喜爱的跨平台应用程序和用户界面开发框架,其核心机制之

    2024年02月20日
    浏览(56)
  • Android页面渲染效率优化实践

      1.车系页布局渲染现状  车系页是重要的车系信息页面,更新迭代多年,页面布局不断变化,xml布局文件越写越复杂。 获取车系页布局文件耗时: 结果如下:   2.卡顿的原因 2.1 Android绘制原理 ► 1.Android的屏幕刷新中涉及到最重要的三个概念 (1)CPU:执行应用层的measure、layo

    2023年04月15日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包