Android导致内存泄露的几种情况和解决方法
16lz
2022-07-23
1.单例模式造成的内存泄漏
public class Utils { private static Utils sInstance; private Context mContext; private AppSettings(Context context) { this.mContext = context; } public static Utils getInstance(Context context) { if (sInstance == null) { sInstance = new Utils(context); } return sInstance; }}
以上单例 context 参数如果传入的是 Activity,Service的上下文对象就会造成内存泄漏,因为静态单例sInstance对象生命周期与 Application 一样长,当 Activity或 Service 销毁时 Utils 还在引用 Activity 或 Service,导致 Activity,Service 不能被回收。
2.非静态内部类内存泄漏
非静态内部类默认持有外部类对象引用。生命周期与应用一样长,所以导致外部类销毁的时候内部类仍然引用外部类,导致外部类不能被回收。
解决方法:改成静态内部类.
典型场景:
//线程匿名内部类new Thread(new Runnable() { @Override public void run() { // 模拟相应耗时逻辑 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start();new AsyncTask() { @Override protected Void doInBackground(Void... params) { // 模拟相应耗时逻辑 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } }.execute();
//线程写成静态内部类private static class MyThread implements Runnable { public void run() { SystemClock.sleep(20000); }}
//Handler造成的内存泄漏public class DemoActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { // ... } }}
由于消息队列持有 handler 引用,handler 又持有 activity 的引用,当消息队列中的消息还没有处理完,activity 就销毁,导致 activity引用仍被使用不能被回收。解决方法:使用静态内部类+弱引用(静态类不会引用 activity,通过弱引用来引用 activity 中的资源)
public static class MyHandler extends Handler { //声明一个弱引用对象 WeakReference mReference; MyHandler(MainActivity activity) { //在构造器中传入Activity,创建弱引用对象 mReference = new WeakReference(activity); } public void handleMessage(Message msg) { //在使用activity之前先判空处理 if (mReference != null && mReference.get() != null) { mReference.get().text.setText("hello word"); } }}@Overrideprotected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null);}
3.静态变量导致内存泄露
静态变量的生命周期与应用一致,当变量被初始化后,它持有的引用到进程结束才会释放。要尽量少的使用静态变量,在适当时候设置 null。
4.未取消注册或回调导致内存泄露
如广播,EventBus注册,在 Activity 销毁后没有取消注册,activity 引用就会被一直持有。销毁时要取消注册。
5.资源对象未及时释放
如Cursor、Stream、Socket,Bitmap等在使用后要及时关闭。
6.集合中的对象未清理造成内存泄露
我们有时会用集合存储对象引用,当对象不用时没有清理集合导致集合越来越大,如果集合是静态的更会造成内存泄漏。要在适当时候clear集合,然后设置为 null。
更多相关文章
- Android(安卓)Resource介绍和使用
- APP开发实战94-Vector静态图的使用
- SlidingMenu和ActionBarSherlock结合做出出色的App布局,Facebook
- Android(安卓)如何开发 Bottom Navigation 风格
- 在android中policymanager
- Android空引用问题的解决方法——on a null object reference
- Android(安卓)ViewHolder
- android 内存缓冲机制:MemoryCache
- android制作一个简单登入界面的部分代码