使用Service时,尽量使用IntentService,这样可以避免忘记关闭服务。
避免一个对象被比它生命周期长的对象持有或引用,这样会导致该对象无法被释放,内存泄露。 如对一个Activity Context保持长生命周期的引用,即使这个Activity已经被销毁了,但相关内存无法被释放。对于生命周期长的对象,可以使用ApplicationContext。 非静态内部类的静态实例容易造成内存泄漏,这个静态实例的生命周期超过了类本身:如Activity中的一些特殊Handler等,尽量使用静态类和弱引用来处理。
BroadCastReceiver要记得注销处理。
在Activity的onDestroy方法中调用handler.removeCallbacksAndMessages(null),取消所有消息的处理,将所有的Callbacks和Messages全部清除掉。
在查询SQLite数据库时,会返回一个Cursor,当查询完毕后,及时关闭。
线程不再需要继续执行的时候要记得及时关闭。 如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程;像HandlerThread的run方法是一个死循环,它不会自己结束,线程的生命周期超过了Activity生命周期,必须手动在Activity的销毁方法中调用thread.getLooper().quit()结束。
属性动画导致内存泄露 在Activity中启动了属性动画(ObjectAnimator),但是在销毁的时候,没有调用cancle方法,虽然我们看不到动画了,但是这个动画依然会不断地播放下去,动画引用所在的控件,所在的控件引用Activity,这就造成Activity无法正常释放。
谨慎使用static对象 因为static的生命周期过长,和应用的进程保持一致,使用不当很可能导致对象泄漏。
有效节省内存,那就极大降低了OOM发生的概率。后面总结一些节省内存的策略。
不要加载过大的Bitmap对象,采用降低图片质量的方法减少内存消耗。Bitmap对象不用时,即使销毁。
批量加载数据时,不要加载的太多,同时进行缓存设计。
在做一些大内存分配等可疑内存操作时进行trycatch操作,避免不必要的应用闪退。 (可以通过ActivityManager的getMemoryClass()来获取APP被分配的可用内存)
注意在ListView/GridView等出现大量重复子组件的视图里面对ConvertView的复用。使用RecyclerView代替ListView/GridView。
避免在onDraw方法里面执行对象的创建. 类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。
多次横竖屏切换 多次横竖屏切换,导致activity的生命周期不断销毁创建,次数多了就OOM。
LruCache(Least Recently Used Cache)
这其实就是一个LinkedHashMap,任意时刻,当一个值被访问时,它就会被移动到队列的开始位置,所以这也是为什么要用LinkedHashMap的原因,因为要频繁的做移动操作,为了提高性能,所以要用LinkedHashMap。当cache满了时,此时再向cache里面添加一个值,那么,在队列最后的值就会从队列里面移除,这个值就有可能被GC回收掉。
这个LruCache在android.util包下,是API level 12引入的,对于API level 12之前的系统可以使用support v4包中的LruCache。
如果我们想主动释放内存,也是可以的,我们可以重写entryRemoved(Boolean, K, V, V)方法。
这个类是线程安全的,在多线程下面使用这个类,不会存在问题。
synchronized (cache) { if (cache.get(key) == null) { cache.put(key, value); }}做好内存优化是一项长期的工作, 需要在很多地方注意,欢迎大家提出平时遇到的内存相关问题或者优化策略,我将持续做好总结。
1.LeakCanary 检测内存泄漏
LeakCanary作为一个简单粗暴的工具,用法也相当简单
首先,在build.gradle中引入LeakCanary。 dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' } 然后,需要在你的application中启动它,LeakCanary是测试整个app的内存泄露情况。 import android.app.Application; import com.squareup.leakcanary.LeakCanary; public class MyApplication extends Application { public static RefWatcher getRefWatcher(Context context) { MyApplication application = (MyApplication) context.getApplicationContext(); return application.refWatcher; } private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher = LeakCanary.install(this); } }更多使用说明
2.BlockCanary 检测卡顿
BlockCanary是一个Android平台的一个非侵入式的性能监控组件,应用只需要实现一个抽象类,提供一些该组件需要的上下文环境,就可以在平时使用应用的时候检测主线程上的各种卡慢问题,并通过组件提供的各种信息分析出原因并进行修复。
具体使用参考文章以及原理分析。
文章部分内容摘自网络,如有不妥请联系本人!