安卓进阶(一)App性能优化

news2024/11/16 13:57:14

文章目录

  • 性能优化的目的及方向
    • 流畅性
      • 启动速度
      • 页面显示速度
      • 响应速度
    • 稳定性
      • ANR
      • Crash
    • 资源节省性
  • 布局优化
    • 选择耗费性能较少的布局
    • 减少布局的层级(嵌套)
    • 使用布局标签
      • 尽量少用布局属性wrap_content
      • include
      • merge
      • include与merge的区别
      • ViewStub
  • 内存泄露
    • 常见内存泄露原因
      • 集合类添加元素
      • Static关键字修饰成员
      • 非静态内部类 / 匿名类
      • 资源对象使用后未关闭
  • 内存优化

性能优化的目的及方向

性能优化的目的是为了让应用程序App 更快、更稳定 & 更省。具体介绍如下:

  • 更快:应用程序 运行得更加流畅、不卡顿,能快速响应用户操作
  • 更稳定:应用程序 能 稳定运行 & 解决用户需求,在用户使用过程中不出现应用程序崩溃(Crash) 和 无响应(ANR)的问题
  • 更省:节省耗费的资源,包括 内存占有、电池量、网络资源等

针对上述目的,APP优化的指标就是:流畅性、稳定性、资源节省性。

具体实现如下:

在这里插入图片描述

流畅性

减少使用中的卡顿、响应时间久等问题,给用户一个操作流畅的体验,主要针对3个方面进行优化:

  • 启动速度
  • 页面显示速度
  • 响应速度

启动速度

优化原因:初次加载应用,需要加载很多资源或者逻辑功能。

优化方案:采用异步加载(多线程)、分步加载、延期加载等策略,减少启动应用时的加载任务,从而提高启动速度。

页面显示速度

优化原因:页面需绘制的内容(布局或控件)太多,导致页面测量时间太长;页面绘制效率过低,导致绘制时间过长。

优化方案:布局优化与绘制优化

响应速度

优化原因:应用程序出现 ANR 情况,从而导致 应用程序响应速度慢

优化方案:使用多线程,将大量耗时操作放在工作线程中执行。

优化方案:使用多线程,将大量耗时操作放在工作线程中执行,比如AsyncTask,HandlerThread等等

稳定性

影响Android 应用稳定性的原因有很多,主要是:应用崩溃(Crash)、应用无响应(ANR)

ANR

程序出现ANR(Application Not Responding,应用程序无响应),导致应用程序响应慢或者屏幕卡死在一个页面。

常见的ANR原因:

  • 应用在5s内未响应用户输入的事件(按键或触摸)。
  • 广播接收器(BroadcastReceiver)在10s内未完成相关事件的处理。
  • 服务(Service)在20s内无法处理完成。

优化方案:使用多线程,将大量耗时操作放在工作线程中执行,比如AsyncTask,HandlerThread等等

实际开发中,当一个进程发生了ANR,系统会在 /data/anr目录下创建一个文件 traces.txt,通过分析该文件可定位出ANR的原因

Crash

程序出现Crash(崩溃)很多情况是因为内存溢出即OOM。

Android系统为每个应用程序分配的内存有限,当应用程序中出现内存泄露较多,不正常使用内存等情况时,容易导致应用程序出现所需的内存超出系统能够为其分配的内存限额(OOM),从而导致程序崩溃。

解决Crash就是解决OOM,涉及到的工作就是内存优化。

资源节省性

优化原因:由于移动设备的硬件性能有限,故减少应用程序的资源消耗显得十分重要

优化方向:内存大小、安装包大小、耗电量 & 网络流量

主要手段包含:内存优化、减少安装包大小、减少网络流量、减少应用耗电量。
在这里插入图片描述

布局优化

布局性能的好坏主要影响Android中页面显示速度,布局影响性能的实质在于:页面的测量与绘制时间

选择耗费性能较少的布局

  • 耗费低的布局 = 功能简单 = FrameLayout、LinearLayout
  • 耗费高的布局 = 功能复杂 =RelativeLayout

减少布局的层级(嵌套)

  • 原理:布局层级少 ->> 绘制的工作量少 ->> 绘制速度快 ->> 性能提高
  • 优化方式:使用布局标签 & 合适选择布局类型

注意:宁愿选择1个耗费性能高的布局,也不采用嵌套多个耗费性能低的布局

使用布局标签

尽量少用布局属性wrap_content

布局属性wrap_content 会增加布局测量时计算成本,应尽可能少用;特别是在已知宽高为固定值时,不使用wrap_content。

include

include>标签可以实现在一个layout中引用另一个layout的布局,这通常适合于界面布局复杂、不同界面有共用布局的APP中,比如一个APP的顶部布局、侧边栏布局、底部Tab栏布局、ListView和GridView每一项的布局等,将这些同一个APP中有多个界面用到的布局抽取出来再通过<include>标签引用,既可以降低layout的复杂度,又可以做到布局重用(布局有改动时只需要修改一个地方就可以了)。

merge

merge标签是用来帮助在视图树中减少重复布局的,当一个layout包含另外一个layout时。
merge使用的要点:

  • merge必须放在布局文件的根节点上
  • merge并不是一个ViewGroup,也不是一个View,它相当于声明了一些视图,等待被添加。
  • merge标签被添加到A容器下,那么merge下的所有视图将被添加到A容器下。
  • 因为merge不是View,所有它没法设置标签属性,或者说设置了是无效的。
  • 因为merge标签并不是View,所以在LayoutInflate.inflate方法渲染的时候,第二个参数必须指定一个父容器,且第三个参数必须为true,也就是必须为merge下的视图指定一个父亲节点。

实例:
不使用merge:
layout1.xml

<FrameLayout>
   <include layout="@layout/layout2"/>
</FrameLayout>

layout2.xml

<FrameLayout>
   <TextView />
</FrameLayout>

实际效果:

<FrameLayout>
   <FrameLayout>
      <TextView />
   </FrameLayout>
</FrameLayout>

使用merge:
layout1.xml

<FrameLayout>
   <include layout="@layout/layout2"/>
</FrameLayout>

layout2.xml

<merge>
   <TextView />
</merge>

实际效果:

<FrameLayout>
   <TextView />
</FrameLayout>

include与merge的区别

从上边的例子中可以看到,include实际上是将另外一个layout完整的嵌入到需要使用的地方。由于所有的组件都必须在ViewGroup中,这就导致了,使用include标签,嵌入时,会多一层ViewGroup,而使用merge则相当于声明了一个虚拟的ViewGroup,使得在include时它可以完全融入merge到需要使用的地方。

ViewStub

ViewStup是一个轻量级的view,之所以说它是轻量级的view是因为它在页面加载渲染的过程中不会去绘制,只是在你需要的时候再去绘制。

ViewStub标签的作用是用于懒加载布局,当系统碰到ViewStub标签的时候是不进行绘制处理(如measure、layout等),比设置View隐藏、不可见更高效。

使用ViewStub的好处:

  • 可以避免ViewStub所对应的视图measure、layout等性能消耗,只有在使用时才会执行,例如在APP启动时提升页面显示速度。
  • 对比invisible和gone的用法,当设置为invisible,view对象会占用位置,只是状态不可见,对象还是会被创建、初始化、占用资源。如果设置为gone,view在layout布局文件中不占用位置,但对象还是会被创建、初始化、占用资源。

ViewStub的缺点在于不可使用<merge>标签,它在使用上类似于<include>标签

内存泄露

从机制上讲:Java存在GC,理应不存在内存泄露,出现内存泄露的原因仅仅是外部人为原因,无意识地持有对象引用,使得持有引用者的生命周期 > 被引用者的生命周期

常见内存泄露原因

集合类添加元素

内存泄露原因:集合类 添加元素后,仍引用着 集合元素对象,导致该集合元素对象不可被回收,从而 导致内存泄漏

// 通过 循环申请Object 对象 & 将申请的对象逐个放入到集合List
List<Object> objectList = new ArrayList<>();        
       for (int i = 0; i < 10; i++) {
            Object o = new Object();
            objectList.add(o);
            o = null;
        }
// 虽释放了集合元素引用的本身:o=null)
// 但集合List 仍然引用该对象,故垃圾回收器GC 依然不可回收该对象

解决方案:
由于1个集合中有许多元素,故最简单的方法 = 清空集合对象 & 设置为null

// 释放objectList
objectList.clear();
objectList=null;

Static关键字修饰成员

被 Static 关键字修饰的成员变量的生命周期 = 应用程序的生命周期.

泄露原因:被 Static 关键字修饰的成员变量 引用耗费资源过多的实例(如Context),则容易出现该成员变量的生命周期 > 引用实例生命周期的情况,当引用实例需结束生命周期销毁时,会因静态变量的持有而无法被回收,从而出现内存泄露

public class ClassName {
 // 定义1个静态变量
 private static Context mContext;
 //...
// 引用的是Activity的context
 mContext = context; 

// 当Activity需销毁时,由于mContext = 静态 & 生命周期 = 应用程序的生命周期,故 Activity无法被回收,从而出现内存泄露
}

解决方案:

  1. 尽量避免 Static 成员变量引用资源耗费过多的实例(如 Context)。
  2. 使用 弱引用(WeakReference) 代替 强引用 持有实例

非静态内部类 / 匿名类

非静态内部类持有外部类的引用,导致外部类无法被释放。

常见情况有:

  • 非静态内部类中创建静态的实例
  • 多线程:AsyncTask等,当工作线程正在处理任务,它持有外部类的引用,导致外部类无法被GC
  • 消息传递机制:Handler,Handler类持有外部activity的引用,当消息队列中还有未处理的消息时,消息队列中的
    Message持有Handler实例的引用。这种引用依赖关系,导致Activity无法被销毁。

在这里插入图片描述

资源对象使用后未关闭

泄露原因:对于资源的使用(如广播、文件流、数据库操作的游标、图片资源BitMap),若在Activity销毁时,没有及时关闭或注销这些资源,从而导致内存泄露。

解决方案:
在Activity销毁时:及时关闭 / 注销资源

内存优化

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605251.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络实验:交换机的Telnet远程登录配置

目录 前言实验目的实验内容实验过程画出拓扑图设置IP3&#xff0c;给交换机设IP&#xff0c;实际上相当于给VLAN 1 这个接口设置IP4&#xff0c;连网线5&#xff0c;测试网络是否连通6&#xff0c;通过telnet去管理配置交换机交换机的密码2、console密码3、telnet密码 总结 前言…

【CSS3系列】第五章 · web 字体

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

【3DsMAX】从零开始建房(1)

目录 目标 步骤 1. 制作地基 2. 制作台阶 3. 制作地砖 4. 制作第一层主体 5. 挖空第一层门的位置 6. 制作展示厅 目标 要做的房子模型如下&#xff1a; 步骤 1. 制作地基 首先创建一个长方体 可以将其转换为可编辑多边形&#xff0c;然后选中所有顶点&#xff0c;调…

【复变函数笔记】解析函数的定义和性质

文章目录 解析函数的等价定义解析函数的性质 解析函数的等价定义 解析函数的定义&#xff1a; f ( z ) f(z) f(z)在区域内可导则在区域内解析&#xff0c;在一点解析就是在某一邻域内可导。解析函数不可能只在一点解析。柯西-黎曼方程&#xff1a;函数 f ( z ) u ( x , y ) …

【TreeSet集合】比较器排序Comparator的使用

比较器排序Comparator的使用 存储学生对象并遍历&#xff0c;创建TreeSet集合使用带参构造方法 要求&#xff1a;按照年龄从小到大排序&#xff0c;年龄相同时&#xff0c;按照姓名的字母顺序排序 创建学生类&#xff1a; package com.gather.set.treeset; public class Stude…

Nginx网站服务——编译安装与系统服务添加

一、Nginx简介 Nginx特点&#xff1a;&#xff08;占用内存少&#xff0c;并发能力强&#xff09; Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启…

makefile编译debug版本调试时无法定位到源文件:No source available for “main() at 0x8544“

问题 之前用makefile编译了一个release版本的可执行文件&#xff0c;但是后面想调试的时候发现无法调试。 觉得-g就能解决问题&#xff0c;后面发现根本不行。 这里虽然加了-g选项&#xff0c;但是调试的时候还是出现找不到源文件的情况。 解决方案 对已有的C/C工程用mak…

Backtrader官方中文文档:第三章Quickstart Guide快速入门

本文档参考backtrader官方文档&#xff0c;是官方文档的完整中文翻译&#xff0c;可作为backtrader中文教程、backtrader中文参考手册、backtrader中文开发手册、backtrader入门资料使用。 快速入门章节目录 快速入门使用平台从0到100&#xff1a;一步一步的演示基本设置设置现…

2023PS beta 爱国版注册安装教程

软件介绍 主要新功能包括: Generative Fill功能(仅在Photoshop Beta桌面应用程序中可用)。这是一个新的工具,可以使用简单的文本提示非破坏性地添加,扩展或删除图像中的内容,以实现令人惊喜,高兴和震惊的真实结果——几秒钟内。要使用此功能,请选择图像中的目标对象或区域,然…

全局流控 or 端到端拥塞控制

同事推荐一篇论文 Bolt: Sub-RTT Congestion Control for Ultra-Low Latency&#xff0c;写点想法。 端到端原则使网络在拥塞控制中始终扮演配角&#xff0c;人们认为拥塞控制是端到端的事。几十年来人们设计的拥塞控制机制始终围绕 “主机在什么情况下要增减 cwnd” 打转。但…

MongoDB 分片集的基本概念

什么是分片集&#xff1f; 副本集&#xff08;ReplicaSet&#xff09; 用于解决读请求扩展、高可用等问题。但随着业务场景的进一步增长&#xff0c;可能会出现以下问题&#xff1a; 存储容量超出单机磁盘容量&#xff1b;活跃数据集超出单机内存容量&#xff0c;很多读请求需…

使用Python将《青花瓷》歌词生成词云图

哈喽大家好&#xff0c;因为上次有小伙伴问我&#xff0c;歌曲的歌词和评论怎么生成词云图&#xff0c;想买代码… 当时我就拒绝了&#xff0c;直接免费送给了他。 所以今天来分享给大家 我们以周董的《青花瓷》为例&#xff0c;要对《青花瓷》歌词生成词云图&#xff0c;需…

[Flash][AS3]“懒惰式引用计数回收内存“导致程序崩溃(闪退)

最近在做Flash项目时候发现&#xff0c;Flash CS6 发布的程序在运行超过两个小时后会闪退&#xff0c;在仔细检查脚本代码和资源文件后&#xff0c;排除了这两个方面的原因。又猜测是内存或者GDI泄漏&#xff0c;在任务管理器中观察了一段时间&#xff0c;程序的GDI没有任何变化…

电脑开机总是卡到不能动怎么重装系统?

电脑开机总是卡到不能动怎么重装系统&#xff1f;有用户反馈自己的电脑在开机之后&#xff0c;总是会出现卡死的情况&#xff0c;无法进行任何的操作。遇到这个问题我们可以使用U盘重装系统的方法来进行电脑系统的重装&#xff0c;接下来我们一起来看看以下具体的操作步骤教学吧…

3.7 图像压缩

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.什么是图像压缩&#xff1f; 在动态规划中&#xff0c;图像压缩是指通过减少图像数据的存储空间&#xff0c;以实现图像文件的压缩和存储优化。动态规…

chatgpt赋能python:从后往前取:Python列表的高效操作

从后往前取&#xff1a;Python列表的高效操作 在Python编程中&#xff0c;列表&#xff08;List&#xff09;是最常用的数据类型之一。列表可以保存任意类型的元素&#xff0c;比如数字、字符串、甚至是其他列表等。在这篇文章中&#xff0c;我们将关注Python列表中从后往前取…

【CSS3系列】第四章 · CSS3新增渐变

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

chatgpt赋能python:Python列表全排列

Python列表全排列 列表是Python中最常用的数据结构之一&#xff0c;它允许我们将多个值&#xff08;数据&#xff09;存储在一个变量中。在Python中&#xff0c;有时我们需要对列表中的元素进行全排列&#xff0c;也就是根据不同的顺序重新排列列表中的元素。本文将介绍如何在…

计算机网络实验:交换机的基本配置与管理

目录 前言实验目的实验内容实验过程总结 前言 本实验旨在了解交换机的基本功能和工作原理&#xff0c;掌握交换机的配置方法和命令&#xff0c;学习交换机端口的基本设置和管理&#xff0c;以及交换机MAC地址表的查看和维护。通过本实验&#xff0c;学生可以熟悉交换机的操作界…

远程面试阿里、蚂蚁、京东、美团后整理份283页Java核心面试宝典

本文整理了一些面试时面试官必问的知识点&#xff0c;其中包括了有基础知识、Java集合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。 以下是文档涉及的主要内容&#xff1a; &#…