关闭

android 内存性能优化

标签: android内存性能优化内存泄露
177人阅读 评论(0) 收藏 举报
分类:
android 内存优化和性能优化问题

一.内存优化

Android应用开发中常出现的一种内存问题就是内存泄露OOM,内存泄漏的能导致问题就是

1:应用卡顿,响应速度慢(内存占用高时JVM虚拟机会频繁触发GC);

2.应用莫名的崩溃(上面应用内存原理有介绍,也就是超过了阈值OOM);

1.内存泄漏的常见情况分析


    1.1.Context使用不当造成内存泄露;不要对一个Activity Context保持长生命周期的引用(譬如上面概念部分给出的示例)。尽量在一切可以使用应用 ApplicationContext代替Context的地方进行替换(原理我前面有一篇关于Context的文章有解释)。
    
    1.2.非静态内部类的静态实例容易造成内存泄漏;即一个类中如果你不能够控制它其中内部类的生命周期(譬如Activity中的一些特殊Handler等),则尽量使用静态类和弱引用来处理(譬如ViewRoot的实现)。

    1.3.警惕线程未终止造成的内存泄露;譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程。一个典型的例子就是HandlerThread的run方法是一个死循环,它不会自己结束,线程的生命周期超过了Activity生命周期,我们必须手动在Activity的销毁方法中中调运thread.getLooper().quit();才不会泄露。

    1.4.对象的注册与反注册没有成对出现造成的内存泄露;譬如注册广播接收器、注册观察者(典型的譬如数据库的监听)等。

    1.5.创建与关闭没有成对出现造成的泄露;譬如Cursor资源必须手动关闭,WebView必须手动销毁,流等对象必须手动关闭等。

    1.6.不要在执行频率很高的方法或者循环中创建对象,可以使用HashTable等创建一组对象容器从容器中取那些对象,而不用每次new与释放。

    1.7.避免代码设计模式的错误造成内存泄露;譬如循环引用,A持有B,B持有C,C持有A,这样的设计谁都得不到释放。

2.内存泄漏的检测工具

    2.1.AS的Memory窗口
    2.2.DDMS-Heap内存监测工具
    2.3.leakcanary (参考Android stduio 常用插件那篇博客有介绍使用)

3.Android 规避内存溢出OOM建议

    3.1.时刻记得不要加载过大的Bitmap对象;譬如对于类似图片加载我们要通过BitmapFactory.Options设置图片的一些采样比率和复用等,具体做法点我参考官方文档,不过过我们一般都用fresco或Glide开源库进行加载。

    3.2.优化界面交互过程中频繁的内存使用;譬如在列表等操作中只加载可见区域的Bitmap、滑动时不加载、停止滑动后再开始加载。

    3.3.有些地方避免使用强引用,替换为弱引用等操作。

    3.4.避免各种内存泄露的存在导致OOM。

    3.5.对批量加载等操作进行缓存设计,譬如列表图片显示,Adapter的convertView缓存等。

    3.6.尽可能的复用资源;譬如系统本身有很多字符串、颜色、图片、动画、样式以及简单布局等资源可供我们直接使用,我们自己也要尽量复用style等资源达到节约内存。

    3.7.对于有缓存等存在的应用尽量实现onLowMemory()和onTrimMemory()方法。

    3.8.尽量使用线程池替代多线程操作,这样可以节约内存及CPU占用率。

    3.9.尽量管理好自己的Service、Thread等后台的生命周期,不要浪费内存占用。

    3.10.尽可能的不要使用依赖注入,中看不中用。

    3.11.尽量在做一些大内存分配等可疑内存操作时进行try catch操作,避免不必要的应用闪退。

4.垃圾回收机制

  先来说说内存优化中的GC (垃圾回收机制),垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。对于GC来说,对象的不同引用强度对于何时回收是不同的。gc其实是在一个优先级较低的线程中执行的,虚拟机在执行GC垃圾回收操作时所有线程(包括UI线程)都需要暂停,当GC垃圾回收完成之后所有线程才能够继续执行,大量GC操作可能会导致界面卡顿的问题。
   4.1 强引用 StrongReference
     一般我们常用到的引用就是强引用,常见形式如:A a = new A();等。强引用本身存储在栈内存中,其存储指向对内存中对象的地址。一般情况下,
     当对内存中的对象不再有任何强引用指向它时,垃圾回收机器开始考虑可能要对此内存进行的垃圾回收。如当进行编码:a = null,此时,刚刚在堆中分配地址并新建的a对象没有其他的任何引用,当系统进行垃圾回收时,堆内存将被垃圾回收。
   4.2 软引用 SoftReference
     对于GC来说, SoftReference的强度明显低于 SrongReference。 SoftReference修饰的引用,其告诉GC:我是一个 软引用,当内存不足的时候,
     我指向的这个内存是可以给你释放掉的,来看一下android系统中的一个使用实列
     private SoftReference<Bitmap> mBitmapCache = new SoftReference<Bitmap>(null);
  public Bitmap getIpMessageBitmap() {
    return mBitmapCache.get();
  }
  public void setIpMessageBitmapCache(Bitmap bitmap) {
    if (null != bitmap) {
      mBitmapCache = new SoftReference<Bitmap>(bitmap);
    }
  }
   4.3 弱引用WeakReference:
      对于GC来说, WeakReference 的强度又明显低于 SoftReference 。 WeakReference 修饰的引用,其告诉GC:我是一个弱 引用,对于你的要求我没有话说, 我指向的这个内存是可以给你释放掉的。我们来看一下android系统中的一个使用实列(InstalledAppDetails.java 这是一段停用一个APP的代码段,其中这个 需要停用APP的InstalledAppDetails对象 在这里的引用就采用了弱引用
  static class DisableChanger extends AsyncTask<Object, Object, Object> {
  final PackageManager mPm;
  final WeakReference<InstalledAppDetails> mActivity;
  final ApplicationInfo mInfo;
  final int mState;

  DisableChanger(InstalledAppDetails activity, ApplicationInfo info, int state) {
      mPm = activity.mPm;
      mActivity = new WeakReference<InstalledAppDetails>(activity);
      mInfo = info;
      mState = state;
  }
    }
    4.4 虚引用 PhantomReference:
    PhantomReference并不会改变其指示对象的垃圾回收时机,ReferenceQueue的作用主要是用于监听SoftReference/WeakReference/PhantomReference的指示对象是否已经被垃圾回收。


二.应用UI性能问题

1 应用UI卡顿常见原因    

    1.1.人为在UI线程中做耗时操作,导致UI线程卡顿;
    1.2.布局Layout过于复杂,无法在一定时间内完成渲染;   
    1.3.View过度绘制或动画效果的过度使用,从而使CPU或GPU负载过重;
    1.4.View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染;
    1.5.内存频繁触发GC过多(同一帧中频繁创建内存),导致暂时阻塞渲染操作;   
    1.6.ANR;(1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
     2.BroadcastReceiver在10秒内没有执行完毕:造成以上两点的原因有很多主线程中做了非常耗时的操作,比如说是下载,io异常)

2.应用UI性能分析解决


    2.1.布局优化;尽量使用include、merge、ViewStub标签,尽量不存在冗余嵌套及过于复杂布局(譬如10层就会直接异常),尽量使用GONE替换INVISIBLE,使用weight后尽量将width和heigh设置为0dp减少运算,Item存在非常复杂的嵌套时考虑使用自定义Item View来取代,减少measure与layout次数等。
    2.2.列表及Adapter优化;尽量复用getView方法中的相关View,不重复获取实例导致卡顿,列表尽量在滑动过程中不进行UI元素刷新等。
    2.3.背景和图片等内存分配优化;尽量减少不必要的背景设置,图片尽量压缩处理显示,尽量避免频繁内存抖动等问题出现。
    2.4.自定义View等绘图与布局优化;尽量避免在draw、measure、layout中做过于耗时及耗内存操作,尤其是draw方法中,尽量减少draw、measure、layout等执行次数。

    2.5.避免ANR,不要在UI线程中做耗时操作,遵守ANR规避守则,譬如多次数据库操作等。


参考博客:

1.http://blog.csdn.net/u010687392/article/details/50721437  内存优化

http://blog.csdn.net/u010687392/article/details/47809295    hashmap 的替代

0
0

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