Android性能优化

最近在看《开发艺术探索》,写的很棒的一本书,大家有时间可以看看,今天再次看了一下 Android性能优化。

Android的内存和CPU的使用都受到了限制,不能像PC机那样使用内存和CPU ,过多的使用内存会造成OOM(内存溢出);过多的使用CPU资源,即执行大型的耗时任务,会造成程序卡顿,甚至会发生ANR(程序无响应),因此,Android的性能问题在编程时很重要。下面介绍一些Android性能优化的方法,有一些我也理解的不透彻。

一.布局优化

我们知道android的界面很多都是布局层级的嵌套,即View树,在写XML文件时,要做到布局优化,就要尽量减少布局层级,这样View在绘制过程中的工作量就会减少。

首先避免写布局中的无用控件和层级,再者,选择相对效率高的布局,比如,可以用RelativeLayout 也可以用 LinearLayout ,在层级相同的情况下,选择LinearLayout ,因为RelativeLayout 的布局过程较复杂。

布局的优化还有以下三种:

(1)使用<include>标签

作用:将指定的布局文件加载到当前布局文件,举个例子:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <include layout="@layout/titlebar"/>
    
</LinearLayout>

如果还要制定其他的属性 , include只支持layout_开头的属性,还有 id,如下面所示

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <include 
        android:id="@+id/new_title"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        layout="@layout/titlebar"/>
    
</LinearLayout>
其他的属性,比如background 这些,在titlebar.xml文件中实现即可。

(2)使用<merge>标签

<merge>标签一般和<include>一起使用,见很少布局的层级,比如,当前布局是一个水平方向的LinearLayout ,其内部也包含一个竖直方向的LinearLayout ,那么就可以通过<merge>标签去掉多余的内部布局文件。

(3)ViewStub

作用:在需要的时候加载所需的布局文件,本身不参与任何的布局和绘制过程

注意:不支持<merge>标签

ViewStub是继承自View,

它的使用场景,比如网络异常时的界面,这个没有必要再整个界面初始化的时候将其加载进来,即可用ViewStub。

如下所示,android:id是ViewStub的id,而android:inflatedId是布局的根元素的id。

<ViewStub android:id="@+id/xxx"
  android:inflatedId="@+id/yyy"
  android:layout="@layout/zzz"
  ...
</ViewStub>
需要加载ViewStub中的布局的时候,可以按照如下两种方式进行:

((ViewStub)findViewById(R.id.xx)).setVisibility(View.VISIBLE);
或者

View importPanel = ((ViewStub)findViewById(R.id.stub_import)).inflate();

二,绘制优化


绘制优化是指View的onDraw方法要避免执行大量的操作:

  • 在onDraw中不要创建新的局部对象,这是因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁的gc,降低了程序的执行效率。
  • onDraw方法中不要指定耗时任务,也不能执行成千上万次的循环操作,View的绘制帧率保证60fps是最佳的,这就要求每帧的绘制时间不超过16ms,虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法的复杂度总是切实有效的。
三,内存泄漏优化

(1)静态变量导致

(2)单例模式导致  因为单例模式的生命周期和Application保持一致。

(3)属性动画   比如动画一直在播放

四,响应速度优化和ANR日志分析

  1. ANR出现的情况:Activity如果5秒内没有响应屏幕触摸事件或者键盘输入事件就会ANR。而BroadcastReceiver如果10s没有执行完操作也会出现ANR。
  2. 当一个进程发生了ANR之后,系统会在/data/anr目录下创建一个文件traces.txt,通过分析这个文件就能定位ANR的原因。
五,ListView和Bitmap优化

  1. ListView优化:采用ViewHolder并避免在getView方法中执行耗时操作;根据列表的滑动状态来绘制任务的执行效率;可以尝试开启硬件加速期来使ListView的滑动更加流畅。
  2. Bitmap优化:根据需要对图片进行采样,主要是通过BitmapFactory.Options来根据需要对图片进行采样,采样主要用到了BitmapFactory.Options的inSampleSize参数。
六,线程优化

采用线程池,避免程序中存在大量的Thread。线程池可以重用内部的线程,从而避免了线程的创建和销毁所带来的性能开销,同时线程池还能有效的控制线程池的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象的发生。

关于性能优化的一些注意点:

  • 避免 创建过多的对象
  • 不要过多的使用枚举,枚举占用的内存空间要比整形大
  • 常量请用static final来修饰
  • 使用一些Android特有的数据结构,比如SparseArray和Pair等,它们都具有更好的性能
  • 适当使用软引用和弱引用
  • 采用内存缓存和磁盘缓存
  • 尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄漏
对于内存泄漏那块,是有分析工具MAT,可以试着测试一下自己的项目,看一下有没有内存泄漏。

如有不足之处,请多多指教。




已经博主授权,源码转载自 https://pan.quark.cn/s/a4b39357ea24 QueueForMcu 基于单片机实现的队列功能模块,主要用于8位、16位、32位非运行RTOS的单片机应用,兼容大多数单片机平台。 开源代码:https://.com/xiaoxinpro/QueueForMcu 一、特性 动态创建队列对象 动态设置队列数据缓冲区 静态指定队列元素数据长度 采用值传递的方式保存队列数据 二、快速使用 三、配置说明 目前QueueForMcu只有一个静态配置项,具体如下: 在文件 中有一个宏定义 用于指定队列元素的数据长度,默认是 ,可以根据需要更改为其他数据类型。 四、数据结构 队列的数据结构为 用于保存队列的状态,源码如下: 其中 为配置项中自定义的数据类型。 五、创建队列 1、创建队列缓存 由于我们采用值传递的方式保存队列数据,因此我们在创建队列前要手动创建一个队列缓存区,用于存放队列数据。 以上代码即创建一个大小为 的队列缓存区。 2、创建队列结构 接下来使用 创建队列结构,用于保存队列的状态: 3、初始化队列 准备好队列缓存和队列结构后调用 函数来创建队列,该函数原型如下: 参数说明: 参考代码: 六、压入队列 1、单数据压入 将数据压入队列尾部使用 函数,该函数原型如下: 参数说明: 返回值说明: 该函数会返回一个 枚举数据类型,返回值会根据队列状态返回以下几个值: 参考代码: 2、多数据压入 若需要将多个数据(数组)压入队列可以使用 函数,原理上循环调用 函数来实现的,函数原型如下: 参数说明: 当数组长度大于队列剩余长度时,数组多余的数据将被忽略。 返回值说明: 该函数将返回实际被压入到队列中的数据长度。 当队列中的剩余长度富余...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值