Android性能优化典例

原文地址:http://blog.csdn.net/u010687392/article/details/47813475

在Android开发过程中,很多时候往往因为代码的不规范、api使用不恰当、控件的使用场景考虑不全面和用户不恰当的操作等都能引发一系列性能问题的,下面就是我目前整理的一些Android开发过程中需要注意的细节,正所谓一颗老鼠屎可以坏了一锅粥,细节决定成败

下面就是一些性能优化的方案:


1、Android中别使用enum,使用static final 代替枚举enum,因为使用enum比使用static需要消耗更多的内存空间


2、Toast中使用getApplicationContext()来代替当前Activity的Context,如Toast.makeText(getApplicationContext(),"",Toast.LENGTH_SHORT).show(); 
因为如果使用当前Activity的Context,当用户操作不当时,比如在Toast显示时候按了返回键,而此时Toast又持有当前Activity的Context引用,所以导致内存泄漏


3、Android开发中合理的使用static,因为static的生命和应用的生命一样长,如果该变量可以的话则不要用static修饰,让它和Actiity保持一样的生命周期或者和方法保持一样的生命周期


4、关于网络请求,如果使用的非常频繁则会对用户手机的电量和流量造成比较大的损耗,正所谓应用的开发应把用户体验放在第一位,所以在网络请求方面,应尽量遵循这两个原则: 
1、减少移动网络被激活的时间与次数(保证应用功能正常使用的前提下) 
2、对一些与用户交互的比较大的数据(图片、文件等),可以对这些数据进行压缩


5、防止内存抖动,所谓内存抖动就是在短时间内创建出大量的对象,从而造成内存紧张,进而触发GC回收,因为执行GC的回收的时候,所有的线程都会暂停,包括主线程,只有等待GC回收完成后其它操作才能继续进行,通常情况下GC回收的效率是非常高效的,但是如果内存上发生大量内存抖动,那么将会导致GC的回收效率降低。所以内存抖动很可能会造成界面卡顿。 
防止内存抖动: 
1、可以使用对象池来管理对象,减少对象创建的次数,在使用完成之后再手动释放对象池中的对象 
2、不要在for、while等循环体中执行对象的创建 
3、避免在onDraw()方法中执行对象的创建 
4、采用预分配策略来减少一次性创建大量的数据

预分配:就是在程序刚启动的时候就事先创建一些即将要使用到的数据,这样可以在需要使用到这些数据的时候提供更快的加载速度,这种行为就叫做预分配


6、针对自定义View,我们在

  • 我们知道调用View.invalidate()会触发View的重绘,有两个原则需要遵守: 
    1、仅仅在View的内容发生改变的时候才去触发invalidate方法 
    2、尽量使用ClipRect等方法来提高绘制的性能
  • 减少绘制时不必要的绘制元素,对于那些不可见的元素,我们需要尽量避免重绘
  • 不要在onDraw()方法中执行内存分配的操作,如:不要在onDraw()方法中执行Paint mPaint = new Paint();等操作
  • 对于不在屏幕上的元素,可以使用Canvas.quickReject把他们给剔除,避免浪费CPU资源。另外尽量使用GPU来进行UI的渲染,这样能够极大的提高程序的整体表现性能

1、使用 Maven 依赖方案代替使用导入jar包方案

如果项目中需要用到第三方jar包,常用的做法是去网上下载后然后放入libs文件夹,再添加到项目依赖,不过,在Android Studio已经不推荐使用这套做法了,因为如果jar有更新,那么每次都要去下载最新版本然后删除历史依赖再添加新版本的依赖,这样做很繁琐,而在Android Studio中,这个问题使用Maven已经很好的解决了,因为AS中默认的是jcenter中央库,而jcenter默认会同步Maven中央库,所以我们可以使用Gradle来添加依赖来代替之前的做法,例如:

dependencies {
    compile 'com.android.support:appcompat-v7:22.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.android.support:recyclerview-v7:22.+'
    compile 'com.android.support:cardview-v7:22.2.+'
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们这样使用,就指定了一个版本范围,当构建项目时候会自动从Maven库中获取指定范围的最新版本的jar包资源

2、避免深层次的布局结构(最多不要超过5层)

复杂的结构可以考虑用相对布局

3、将相同控件的相同属性抽取出来为一个style

例如: 
假如有若干个Button,而Button的样式都是统一的,这时候我们可以将Button的字体大小、颜色、背景色、字体类型等抽取出来放在一个style中,供多个Button复用,如:

<style name="MyButton" parent="Base.Widget.AppCompat.Button">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">#ffffff</item>
        <item name="android:background">#202020</item>
        <item name="android:typeface">sans</item>
</style>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

layout布局:

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

    <Button
        style="@style/MyButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Space
        android:layout_width="match_parent"
        android:layout_height="10dp" />

    <Button
        style="@style/MyButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/action_settings" />

    <Space
        android:layout_width="match_parent"
        android:layout_height="10dp" />

    <Button
        style="@style/MyButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/app_name" />
</LinearLayout>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

效果: 
这里写图片描述

可以看到这三个Button的样式都一样,复用了相同的style

4、慎用AsyncTask,使用网络请求框架(Volley、OkHttp)代替

关于AsyncTask在异步网络请求方面用的非常多,因为它使用起来比较轻量,但是关于AsyncTask也存在内存泄漏和结果丢失等问题,下面一起来看看:

1、内存泄漏

如果在Activity中使用AsyncTask以匿名内部类的方式请求网络,由于AsyncTask的生命周期可以比Activity的长(因为请求网络数据是比较耗时的),AsyncTask内部类持有Activity的引用的话,如果还在请求网络时就关闭了Activity,那么将导致Activity对象将无法回收,进而产生内存泄漏

2、结果丢失

假如Activity的launchMode是默认或者是标准的,那么当AsyncTask在请求网络数据时把屏幕旋转了,那么将会重新创建一个新的Activity,又因为还在运行的AsyncTask持有之前Activity的引用,那么将导致onPostExecute()方法不起任何作用,请求获得的数据不能加载到新的Activity上,而且也将导致内存泄漏

3、串行和并行多版本不一致

AsyncTask在1.6之前为串行,在1.6-2.3为并行,在3.0之后又改为串行,在3.0之后虽然可以通过代码来改变默认的串行为并行,但是又是一个繁琐的操作


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值