关闭

Android性能优化

标签: 性能优化
174人阅读 评论(0) 收藏 举报
分类:
  • 使用LocalBroadcastManager

使用Context的registerReceiver和sendBroadCast注册发送广播是全局范围的,或者说是整个系统范围的,而LocalBroadcastManager限定只在我们的app进程中,不用担心广播发送的数据往外泄露,同时外部应用也无法通过广播调起我们的app,因此更加安全。

  • convertView复用

如果使用ListView或者GridView,注意convertView复用以及ViewHolder的使用,可以不用每次都创建新的布局以及进行findViewById这样费时的操作,即使某种itemType类型的itemView数量只有一个。推荐使用RecyclerView,功能更强大,性能更好,并且为我们封装好了View复用工作。

  • 合理使用Context

如果需要保存Context信息,尽量使用ApplicationContext,以防内存泄漏。不过,ApplicationContext也不是万能的,ApplicationContext不能用来创建Dialog,不能直接用来启动Activity(需要设置FLAG_ACTIVITY_NEW_TASK标识位),使用ApplicationContext创建的布局使用的是默认的主题样式。如果使用的不是ApplicationContext,切记及时释放Context。

  • 尽量避免使用非静态内部类

Android中创建内部类的情况有很多,例如创建ViewHolder,Adapter等等。如果可以,应该尽量使用静态内部类。一方面,静态内部类不持有外部类的引用,可以一定程度上防止内存泄漏的风险;另一方面,静态内部类不能访问外部类非静态方法,编译时不用为内部类生成访问外部类的接口。

  • SparseArray替代HashMap

SparseArray底层keys和values分别使用数组存储,添加、删除等操作使用binary search二分查找;使用int基本类型作为key类型,避免autobox带来的性能损失;另外,删除操作并不会真的直接移除key和value,只是做了一个DELETED标记,特定时候再统一gc。类似的还有SparseBooleanArray、SparseIntArray、SparseLongArray。

  • 尽量避免使用枚举类型enum

Android对于内存较为敏感,而enum会带来额外的内存开销,在没有必要需求的情况下,例如,定义几个int类型常量type,可以考虑使用final static int代替。官方文档说大概会比静态常量大2倍多。具体计算分析可以参考这篇介绍:Android 中的 Enum 到底占多少内存?该如何用?

  • onPause、onStop释放不必要的资源

在Activity跳转时,onPause和onStop会回调,可以释放一些资源,例如暂停视频音频播放,暂停动画等。但是,同时需要注意的是,不要在onPause中做过多复杂的操作。因此我们知道Activity跳转时,会先回调当前Actiity的onPause方法,如果操作过于复杂,会明显影响Activity跳转速度,带来不好的用户体验。

  • onDraw最好不要进行new操作

很容易造成内存频繁分配、回收,造成内存抖动现象,加大Dalvik虚拟机gc压力。

  • view过度绘制及优化

避免background重复绘制,耗性能。可适当使用ViewStub标签优化性能,减少不必要view的绘制。自定义组件时,可考虑使用merge标签减少层级。使用ReleativeLayout代替LinearLayout完成复杂布局,减少layout层级,单就ReleativeLayout和LinearLayout来说,ReleativeLayout性能不如LinearLayout,但是如果可以减少层级,是划算的。

  • 尽量避免使用依赖注入框架

大部分依赖注入框架,都是基于反射机制实现,编码方便的同时其实降低了App性能。

  • gradle开启ProGuard选项

开启ProGuard选项,打包时可以剔除多余的代码,并且对代码进行混淆,保证代码安全的同时,一定程度上也可以减小dex包大小。需要注意,如果代码中使用了反射可能会报错,可以在proguard rule中配置不对某些特定的类进行混淆来解决问题。另外,开启了ProGuard可能对调试也有影响,导致断点走不到或者查看不到变量值。解决办法是只在release环境下才开启proguard选项,debug模式下不开启。

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }

    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'

    }
}
  • Bitmap使用优化

通常原始的图片大小并不是我们需要的,有时为了节省内存,在使用ImageView控件加载图片前,我们可以设置需要加载到内存中的bitmap大小。例如:

public static Bitmap resizeBitmap(String filename, int requiredWidth, int requiredHeight){
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
    options.inSampleSize = computeSampleSize(options.outWidth, options.outHeight, requiredWidth, requiredHeight);
    options.inJustDecodeBounds = false;
    bitmap = BitmapFactory.decodeFile(filename, options);
    return bitmap;
}

BitmapFactory.Options的inJustDecodeBounds属性设置为true时,不真正加载bitmap到内存中,但是bitmap的宽高等属性都能获取到。经过比例缩放计算后,我们可以设置BitmapFactory.Options的inSampleSize值,表示bitmap的采样大小,即宽高为原始宽高的几分之一,这时候再加载就可以达到节省内存的效果。注意:inSampleSize的值会自动向下优化为最接近的2的n次方。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:11574次
    • 积分:327
    • 等级:
    • 排名:千里之外
    • 原创:21篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论