5个android开发中比较常见的内存泄漏问题及解决办法

上传人:第*** 文档编号:31316172 上传时间:2018-02-06 格式:DOCX 页数:11 大小:23.27KB
返回 下载 相关 举报
5个android开发中比较常见的内存泄漏问题及解决办法_第1页
第1页 / 共11页
5个android开发中比较常见的内存泄漏问题及解决办法_第2页
第2页 / 共11页
5个android开发中比较常见的内存泄漏问题及解决办法_第3页
第3页 / 共11页
5个android开发中比较常见的内存泄漏问题及解决办法_第4页
第4页 / 共11页
5个android开发中比较常见的内存泄漏问题及解决办法_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《5个android开发中比较常见的内存泄漏问题及解决办法》由会员分享,可在线阅读,更多相关《5个android开发中比较常见的内存泄漏问题及解决办法(11页珍藏版)》请在金锄头文库上搜索。

1、5 个 Android 开发中比较常见的内存泄漏问题及解决办法在 Android 开发中,内存泄漏是比较常见的问题,有过一些Android 编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢? 内存泄漏又有什么影响呢?在 Android 程序开发中,当一个对象已经不需要再使用了,本该被回收时,而另外一个正在使用的对象持有它的引用从而导致它不能被回收,这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了。内存泄漏有什么影响呢?它是造成应用程序 OOM 的主要原因之一。由于 Android 系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需

2、要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。了解了内存泄漏的原因及影响后,我们需要做的就是掌握常见的内存泄漏,并在以后的 Android 程序开发中,尽量避免它。下面小编搜罗了 5 个 Android 开发中比较常见的内存泄漏问题及解决办法,分享给大家,一起来看看吧。一、单例造成的内存泄漏Android 的单例模式非常受开发者的喜爱,不过使用的不恰当的话也会造成内存泄漏。因为单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。如下这个典例:

3、public class AppManager private static AppManager instance;private Context context;private AppManager(Context context) this.context = context;public static AppManager getInstance(Context context) if (instance != null) instance = new AppManager(context);return instance;这是一个普通的单例模式,当创建这个单例的时候,由于需要传入一个

4、 Context,所以这个 Context 的生命周期的长短至关重要:1、传入的是 Application 的 Context:这将没有任何问题,因为单例的生命周期和 Application 的一样长 ;2、传入的是 Activity 的 Context:当这个 Context 所对应的 Activity退出时,由于该 Context 和 Activity 的生命周期一样长(Activity 间接继承于 Context),所以当前 Activity 退出时它的内存并不会被回收,因为单例对象持有该 Activity 的引用。所以正确的单例应该修改为下面这种方式:public class AppM

5、anager private static AppManager instance;private Context context;private AppManager(Context context) this.context = context.getApplicationContext();public static AppManager getInstance(Context context) if (instance != null) instance = new AppManager(context);return instance;这样不管传入什么 Context 最终将使用 A

6、pplication 的Context,而单例的生命周期和应用的一样长,这样就防止了内存泄漏。二、非静态内部类创建静态实例造成的内存泄漏有的时候我们可能会在启动频繁的 Activity 中,为了避免重复创建相同的数据资源,会出现这种写法:public class MainActivity extends AppCompatActivity private static TestResource mResource = null;Overrideprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInsta

7、nceState);setContentView(R.layout.activity_main);if(mManager = null)mManager = new TestResource();/.class TestResource /.这样就在 Activity 内部创建了一个非静态内部类的单例,每次启动 Activity 时都会使用该单例的数据,这样虽然避免了资源的重复创建,不过这种写法却会造成内存泄漏,因为非静态内部类默认会持有外部类的引用,而又使用了该非静态内部类创建了一个静态的实例,该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该 Activity 的引用,导致

8、Activity 的内存资源不能正常回收。正确的做法为:将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用 Context,请使用 ApplicationContext 。三、Handler 造成的内存泄漏Handler 的使用造成的内存泄漏问题应该说最为常见了,平时在处理网络任务或者封装一些请求回调等 api 都应该会借助 Handler来处理,对于 Handler 的使用代码编写一不规范即有可能造成内存泄漏,如下示例:public class MainActivity extends AppCompatActivity private Handler mHandler

9、 = new Handler() Overridepublic void handleMessage(Message msg) /.;Overrideprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);loadData();private void loadData()/.requestMessage message = Message.obtain();mHandler.sendMessage(m

10、essage);这种创建 Handler 的方式会造成内存泄漏,由于 mHandler 是Handler 的非静态匿名内部类的实例,所以它持有外部类 Activity 的引用,我们知道消息队列是在一个 Looper 线程中不断轮询处理消息,那么当这个 Activity 退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的 Message 持有 mHandler 实例的引用,mHandler 又持有 Activity 的引用,所以导致该 Activity 的内存资源无法及时回收,引发内存泄漏,所以另外一种做法为:public class MainActivity extends Ap

11、pCompatActivity private MyHandler mHandler = new MyHandler(this);private TextView mTextView ;private static class MyHandler extends Handler private WeakReference reference;public MyHandler(Context context) reference = new WeakReference(context);Overridepublic void handleMessage(Message msg) MainActi

12、vity activity = (MainActivity) reference.get();if(activity != null)activity.mTextView.setText();Overrideprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTextView = (TextView)findViewById(R.id.textview);loadData(); private v

13、oid loadData() /.requestMessage message = Message.obtain();mHandler.sendMessage(message);创建一个静态 Handler 内部类,然后对 Handler 持有的对象使用弱引用,这样在回收时也可以回收 Handler 持有的对象,这样虽然避免了 Activity 泄漏,不过 Looper 线程的消息队列中还是可能会有待处理的消息,所以我们在 Activity 的 Destroy 时或者 Stop 时应该移除消息队列中的消息,更准确的做法如下:public class MainActivity extends A

14、ppCompatActivity private MyHandler mHandler = new MyHandler(this);private TextView mTextView ;private static class MyHandler extends Handler private WeakReference reference;public MyHandler(Context context) reference = new WeakReference(context);Overridepublic void handleMessage(Message msg) MainAct

15、ivity activity = (MainActivity) reference.get();if(activity != null)activity.mTextView.setText(); Overrideprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTextView = (TextView)findViewById(R.id.textview);loadData();private

16、void loadData() /.requestMessage message = Message.obtain();mHandler.sendMessage(message);Overrideprotected void onDestroy() super.onDestroy();mHandler.removeCallbacksAndMessages(null);使用 mHandler.removeCallbacksAndMessages(null);是移除消息队列中所有消息和所有的 Runnable。当然也可以使用mHandler.removeCallbacks();或 mHandler.removeMessages();来移除指定的 Runnable 和 Message。四、线程造成的内存泄漏对于线程造成的内存泄漏

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 中学教育 > 其它中学文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号