新手常见内存问题

内存溢出

抓狂的oom,这个错误抛出的原理

内存泄漏

当内存不足时,Android运行时就会触发GC,GC采用的垃圾标记算法为根搜索算法。内存泄漏就是指没有用的对象到GC root是可达的,导致GC无法回收该对象。

内存泄漏的场景

  1. 非静态内部类的静态实例,如
public class InnerActivity extends AppCompatActivity {
    private static Object inner;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inner);
        //
        inner=new InnerClass();
    }

    class InnerClass{}
}

静态实例inner生命周期与应用程序一样长,它持有InnerActivity的引用,导致InnerActivity无法被回收。

  1. 多线程相关的非静态内部类
public class InnerActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inner);

        startAsyncTask();
    }
    void startAsyncTask(){
        new AsyncTask<Void,Void,Void>(){
            @Override
            protected Void doInBackground(Void... voids) {
                while (true){//耗时任务
                }
            }
        }.execute();
    }
}

AsyncTask的内部匿名类,如果线程不结束,则一直持有Activity的引用。我们可以会使用静态AsyncTask或者退出Activity时结束异步线程。

  1. Handler内存泄露
    HandlerMessage被存储在MessageQueue中, 有些Message不能立即处理,它们会在MessageQueue存在很长时间,这会导致Handler无法被回收。如果Handler是非静态的,则引用它的ActivityService不能被回收。

解决方案:

  • 一个是使用静态的Handler内部类,持有的引用使用弱引用
  • activityDestory方法中,调用handler.removeCallbacksAndMessages(null);来移除MessageQueue中的Message.
  1. 未正确使用Context
    对于不是必须使用Activity的Context情况,可以考虑使用Application Context来代替,特别是单例的情况。

  2. WebView
    在应用中只要使用一次WebView,内存就不会被释放掉。通常的解决办法是为WebView单开一个进程,使用AIDL与应用进行通信。WebView可以根据业务需求在合适的时机进行销毁。

6.资源对象未关闭
资源对象比如Curso、File等,往往都使用了

内存分析

通过内存分析来发现泄漏点

避免内存抖动

频烦的内存申请及释放,会导致短时间的频烦GC,会严重影响程序性能。
解决方法:不要申请大量不必要的对象内存:
1, 不可变对象:String
2, 自动装箱:Integer, Boolean...
考虑使用对象池并缓存来减少内存抖动
留心enum类型的开销(一个指向枚举类型的引用就要占据4个字节)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章