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

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

性能优化的目的及方向

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

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

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

具体实现如下:

安卓进阶(一)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,涉及到的工作就是内存优化。

资源节省性

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

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

主要手段包含:内存优化、减少安装包大小、减少网络流量、减少应用耗电量。
安卓进阶(一)App性能优化

布局优化

布局性能的好坏主要影响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无法被销毁。

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

资源对象使用后未关闭

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

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

内存优化

安卓进阶(一)App性能优化文章来源地址https://www.toymoban.com/news/detail-470033.html

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

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

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

相关文章

  • 前端性能优化进阶版

    1、使用 Web Workers 和 Service Workers 来提高并行性和离线缓存。 使用 Web Workers 和 Service Workers:可以使用 Web Workers 将计算密集型任务放到其他线程中执行,以避免卡顿和阻塞 UI 线程。Service Workers 可以用于缓存网页资源以提高加载速度和离线访问能力。 2、使用 HTTP/2 来减少请求

    2023年04月27日
    浏览(33)
  • Android 性能优化——APP启动优化

            首先在《Android系统和APP启动流程》中我们介绍了 APP 的启动流程,但都是 FW 层的流程,这里我们主要分析一下在 APP 中的启动流程。要了解 APP 层的启动流程,首先要了解 APP 启动的分类。 冷启动         应用从头开始启动,即应用的首次启动。需要做大量的工

    2024年04月12日
    浏览(47)
  • 一本书让你彻底搞懂安卓系统性能优化

    🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 前言 作者简介 内容简介  本书特色 读者对象 直播预告 文末福利         为什么

    2024年02月08日
    浏览(44)
  • 【运维知识进阶篇】集群架构-Nginx性能优化

    Nginx花了好多篇文章介绍了,今天谈谈它的优化。我们从优化考虑的方面,压力测试工具ab,具体的优化点三个方面去介绍,话不多说,直接开始! 目录 优化考虑方面 压力测试工具 性能优化 一、影响性能的指标 二、系统性能优化 1、更改文件句柄 2、Time_wait状态重用 三、代

    2024年02月06日
    浏览(61)
  • MySQL进阶之性能优化与调优技巧

    1.1.2 介绍 多表查询:查询时从多张表中获取所需数据 单表查询的SQL语句:select 字段列表 from 表名; 要执行多表查询,只需要使用逗号分隔多张表即可,如: select 字段列表 from 表1, 表2; 查询用户表和部门表中的数据: 此时,我们看到查询结果中包含了大量的结果集,总共85条

    2024年02月05日
    浏览(59)
  • 前端进阶版本 ,性能优化—-防抖、节流、重绘与回流

    目录 【防抖】 【节流】 重绘(repaint) 回流(reflow):又叫重排(layout) 工作中要如何避免大量使用重绘与回流? 常见的会导致回流的元素 【防抖】 任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。 【节流】 指定时间间隔内只会执行一次任务。

    2024年02月14日
    浏览(38)
  • 一本书让你彻底搞懂安卓系统性能优化(文末送书5本)

    🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 前言 作者简介 内容简介  本书特色 读者对象 直播预告 文末福利         为什么

    2024年02月08日
    浏览(51)
  • Android进阶:ListView性能优化异步加载图片 使滑动效果流畅

    ListView  是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构,可能会从网络上获取icon等的一些图标信息,就现在的网络速度要想保持ListView运行的很好滚动流畅是做不到的 所以这里就需要把这些信息利用多线程实现异步加载 实现这样功能的

    2024年02月16日
    浏览(54)
  • 「NodeJs进阶」超全面的 Node.js 性能优化相关知识梳理

    相信对于前端同学而言,我们去开发一个自己的简单后端程序可以借助很多的nodeJs的框架去进行快速搭建,但是从前端面向后端之后,我们会在很多方面会稍显的有些陌生,比如「性能分析」,「性能测试」,「内存管理」,「内存查看」,「使用C++插件」,「子进程」,「

    2024年02月01日
    浏览(54)
  • 详细教程 - 进阶版 鸿蒙harmonyOS应用 第十八节——鸿蒙OS应用性能优化指南

    性能优化是提升鸿蒙OS应用质量的重要手段。优化的角度包括加载速度、CPU使用率、内存占用、电量消耗、网络流量等多个方面。 本文将通俗解释性能表现的影响因素,并结合实例提供有效的检测分析方法与优化策略建议,帮助开发者系统地提升应用性能与用户体验。 2.1 加载时

    2024年01月16日
    浏览(55)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包