Android内存优化

今天在公众号(安卓巴士Android开发者门户),看到一篇不错的文章,于是就动手写了下,整理了一些地方,分享给大家

一、决所有内存泄漏

  1. 单例泄露

    单例是全局的,和Application一样的生命周期,有时会引用生命周期较短的变量,导致其无法释放。

  • 解决方法

    1. 传入和单例一样生命周期的对象,如context.getApplication()

    2. 不将context保存在单例的成员变量里

  1. Handler AsyncTask等内部类的内存泄漏

    内部类默认持有外部类的引用,jvm在把.java源文件编译成.class字节码的时候,会在默认的构造函数加入外部类的引用,所以我们的内部类也能访问外部类的引用。如果当前Handler持有Activity的引用,Handler不释放,Activity也别想释放。

  • 解决方法

    1. 构造函数传入Activity并用WeakReference弱引用保存,GC的时候会不计入Handler对Activity的引用,可以被回收,WeakReference mreference= new WeakReference(mActivity ); mreference.get()是否为null判断是否被回收

    2. Activity onDestroy() 的时候,把所有的相关请求终止,清空消息队列removeCallbacksAndMessages(null),防止有数据回调到UI

    3. 内部类使用static修饰

  1. 资源使用完后未关闭

    • BraodcastReceiver 注册后要进行反注册,推荐在onStart()和onStop()对应的生命周期中执行

    • Service start()之后要stop(),一般不建议在Application中启动,启动Service耗时基本需要100ms+

    • io 记得要close

    • Bitmap内存大户,要recycle一下,90%的场景Glide已经帮我们处理的

  2. 内存泄漏检测工具

    不可能规避掉所有内存

    • LeakCanary

    • Android Studio profile

    • MAT

二、图片压缩

网络或者本地读取的图片较大,很容易导致OOM

Bitmap.getAllocationByteCount();计算bitmap占用多少内存

  • 解决方法

    对图片进行一定的压缩

    1. 获取图片大小,根据自己需要的大小计算缩放比例

    2. 进行缩放,得出符合自己控件尺寸的大小

    3. BitmapFactory.option属性

三、解决内存抖动

String StringBuffer StringBuilder

使用StringBuiler去拼接字符串,明显效率大于使用+

使用+拼接字符串,jvm会创建一个临时的StringBuilder,然后把上次的结果集通过构造函数传入

再拼接到本次的结果集中,然后存到局部变量表中,等待下次循环,每次都会重新创建一个StringBuilder,而且用完就抛弃,在内存吃紧的情况下很容易gc,导致APP卡顿

而使用StringBuilder则只新建了一个对象,所以效率高

四、尽量使用“池”

池的功能可以重复利用对象,并且减少内存开销,内存抖动,cpu开销等,对于一些大量频繁生成和回收的对象,建议使用池

  • 线程池(RxJava)

  • Lrucache缓存池和LruDiskCache (Glide中使用)

  • okhttp中ConnectionPool(Socket复用池)

  • okio SegmentPool(buffer复用池)

五、其他

  1. 使用常用数据结构优化

    内存大户:HashMap ,这是一个典型的空间换时间,时间复杂度趋近o(1),占用空间大于size/0.75

    所在数据量较小,或者对速度没那么高要求时,可以使用SparseArray(二叉树)代替

  2. xml层级和view

    xml层级最好控制在5层以内

    view多使用

    • ViewStub 需要后期控制view的显示

    • include 引入一个view文件

    • merge 解决 不必要的嵌套

你可能感兴趣的:(android,Android)