Android内存泄漏问题

1.内存泄漏问题

  • GC:garbage collection。
    java内存泄漏是指进程中某些对象(垃圾对象)没有使用价值了,但还可以直接或者间接地引用到gc roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了
  • 内存泄漏危害:
    虚拟机占用内存过高,导致OOM(内存溢出),程序出错。对于Android应用来说,就是你的用户打开一个Activity,使用完之后关闭它,内存泄露;又打开,又关闭,又泄露;几次之后,程序占用内存超过系统限制。

2.常见的内存泄漏问题

  1. 非静态内部类的静态实例容易造成内存泄漏
  2. activity使用静态成员
  3. 使用handler时的内存问题
  4. 注册某个对象后未反注册
  5. 集合中对象没清理造成的内存泄露
  6. 资源对象没关闭造成的内存泄露
  7. 一些不良代码成内存压力

3.具体分析(部分)

3.1 使用Handler的内存问题:

3.1.1 原因:
3.1.2 解决方法:
将Handler声明为静态累类,同时引入弱引用(WeakReference)。如:

   private Handler mHandler = new MyHandler(this);

    private static class MyHandler extends Handler {
    WeakReference mActivityReference;

    MyHandler(Activity activity) {
        mActivityReference= new WeakReference(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        final Activity activity = mActivityReference.get();
        if (activity != null) {
            mImageView.setImageBitmap(mBitmap);
        }
    //activity.get().todo();//toto为需要实现的方法
    }
   }

如果不用弱引用,只在Activity ondestroy的时候调用mHandler.removeCallbacksAndMessages(null)即可。

3.1.3 简单demo

public class HandleMemoryLeadSolve extends Activity {

    private static class MyHandler extends Handler {
        private WeakReference reference;

        public MyHandler(Activity activity) {
            reference = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            HandleMemoryLeadSolve activity = (HandleMemoryLeadSolve) reference.get();
            if (activity != null) {
                Log.d("zyzhang","activity != null"+activity.toString());
            } else {
                Log.d("zyzhang","activity = null");
            }
        }
    }

    private final Handler mHandler = new MyHandler(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zyzhang_memoryleak);

        mHandler.sendEmptyMessageDelayed(0,10000);
        finish();
    }

    @Override
    protected void onDestroy() {
        Log.d("zyzhang", "onDestroy");
        super.onDestroy();
        //解除Handler与Message间的引用
        //mHandler.removeCallbacksAndMessages(null);
    }
}

注:非常遗憾的一点是本人使用上述的软引用测试的时候,系统并没有回收实例内存,不管我设置的时间是10秒还是100秒都是一样的效果(至于原因还在摸索),所以我认为最靠谱的方法就是直接在onDestroy()放在中加入 mHandler.removeCallbacksAndMessages(null);以解除Handler与Message间的引用。

3.2 一些不良代码成内存压力

  • Bitmap使用不当

  • 构造Adapter时,没有使用缓存的 convertView

  • 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用 hashtable , vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次 new 之后又丢弃。

(因时间关系不做过多介绍,后面继续更新)

4内存泄漏的调试

  1. 内存监测工具 DDMS –> Heap

    • 在android Studio工具中找到Tools->Android->Android Device Monitor 。
    • 点击选中想要监测的进程,比如system_process进程。
    • 点击选中Devices视图界面中最上方一排图标中的“Update Heap”图标。
    • 点击Heap视图中的“Cause GC”按钮。(向虚拟机请求了一次gc操作,不需要不断点击)
    • 操作观察数据的变化(如:data object的Total Size值,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏)
  2. 内存分析工具 MAT(Memory Analyzer Tool)
    使用MAT工具是为了更加精准的发现内存泄漏问题。其中Shallow heap表示对象本身所占内存大小,Retained heap表示通过回收这一个对象总共能回收的内存

你可能感兴趣的:(android)