5个Android开发中比较常见的内存泄漏问题及解决办法_第1页
5个Android开发中比较常见的内存泄漏问题及解决办法_第2页
5个Android开发中比较常见的内存泄漏问题及解决办法_第3页
5个Android开发中比较常见的内存泄漏问题及解决办法_第4页
5个Android开发中比较常见的内存泄漏问题及解决办法_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

5 个个 Android 开发中比较常见的开发中比较常见的 内存泄漏问题及解决办法内存泄漏问题及解决办法 在 Android 开发中 内存泄漏是比较常见的问题 有过一些 Android 编程经历的童鞋应该都遇到过 但为什么会出现内存泄漏 呢 内存泄漏又有什么影响呢 在 Android 程序开发中 当一个对象已经不需要再使用了 本 该被回收时 而另外一个正在使用的对象持有它的引用从而导致它 不能被回收 这就导致本该被回收的对象不能被回收而停留在堆内 存中 内存泄漏就产生了 内存泄漏有什么影响呢 它是造成应用程序 OOM 的主要原因之 一 由于 Android 系统为每个应用程序分配的内存有限 当一个应 用中产生的内存泄漏比较多时 就难免会导致应用所需要的内存超 过这个系统分配的内存限额 这就造成了内存溢出而导致应用 Crash 了解了内存泄漏的原因及影响后 我们需要做的就是掌握常见 的内存泄漏 并在以后的 Android 程序开发中 尽量避免它 下面 小编搜罗了 5 个 Android 开发中比较常见的内存泄漏问题及解决办 法 分享给大家 一起来看看吧 一 单例造成的内存泄漏一 单例造成的内存泄漏 Android 的单例模式非常受开发者的喜爱 不过使用的不恰当 的话也会造成内存泄漏 因为单例的静态特性使得单例的生命周期 和应用的生命周期一样长 这就说明了如果一个对象已经不需要使 用了 而单例对象还持有该对象的引用 那么这个对象将不能被正 常回收 这就导致了内存泄漏 如下这个典例 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 这是一个普通的单例模式 当创建这个单例的时候 由于需要 传入一个 Context 所以这个 Context 的生命周期的长短至关重要 1 传入的是 Application 的 Context 这将没有任何问题 因为单例 的生命周期和 Application 的一样长 2 传入的是 Activity 的 Context 当这个 Context 所对应的 Activity 退出时 由于该 Context 和 Activity 的生命周期一样长 Activity 间接 继承于 Context 所以当前 Activity 退出时它的内存并不会被回收 因为单例对象持有该 Activity 的引用 所以正确的单例应该修改为下面这种方式 public class AppManager 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 最终将使用 Application 的 Context 而单例的生命周期和应用的一样长 这样就防止了内存泄 漏 二 非静态内部类创建静态实例造成的内存泄漏二 非静态内部类创建静态实例造成的内存泄漏 有的时候我们可能会在启动频繁的 Activity 中 为了避免重复 创建相同的数据资源 会出现这种写法 public class MainActivity extends AppCompatActivity private static TestResource mResource null Override protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState setContentView R layout activity main if mManager null mManager new TestResource class TestResource 这样就在 Activity 内部创建了一个非静态内部类的单例 每次 启动 Activity 时都会使用该单例的数据 这样虽然避免了资源的重 复创建 不过这种写法却会造成内存泄漏 因为非静态内部类默认 会持有外部类的引用 而又使用了该非静态内部类创建了一个静态 的实例 该实例的生命周期和应用的一样长 这就导致了该静态实 例一直会持有该 Activity 的引用 导致 Activity 的内存资源不能正常 回收 正确的做法为 将该内部类设为静态内部类或将该内部类抽取出来封装成一个 单例 如果需要使用 Context 请使用 ApplicationContext 三 三 Handler 造成的内存泄漏造成的内存泄漏 Handler 的使用造成的内存泄漏问题应该说最为常见了 平时 在处理网络任务或者封装一些请求回调等 api 都应该会借助 Handler 来处理 对于 Handler 的使用代码编写一不规范即有可能造成内存 泄漏 如下示例 public class MainActivity extends AppCompatActivity private Handler mHandler new Handler Override public void handleMessage Message msg Override protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState setContentView R layout activity main loadData private void loadData request Message message Message obtain mHandler sendMessage message 这种创建 Handler 的方式会造成内存泄漏 由于 mHandler 是 Handler 的非静态匿名内部类的实例 所以它持有外部类 Activity 的 引用 我们知道消息队列是在一个 Looper 线程中不断轮询处理消息 那么当这个 Activity 退出时消息队列中还有未处理的消息或者正在 处理消息 而消息队列中的 Message 持有 mHandler 实例的引用 mHandler 又持有 Activity 的引用 所以导致该 Activity 的内存资源 无法及时回收 引发内存泄漏 所以另外一种做法为 public class MainActivity extends AppCompatActivity 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 Override public void handleMessage Message msg MainActivity activity MainActivity reference get if activity null activity mTextView setText Override protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState setContentView R layout activity main mTextView TextView findViewById R id textview loadData private void loadData request Message message Message obtain mHandler sendMessage message 创建一个静态 Handler 内部类 然后对 Handler 持有的对象使 用弱引用 这样在回收时也可以回收 Handler 持有的对象 这样虽 然避免了 Activity 泄漏 不过 Looper 线程的消息队列中还是可能会 有待处理的消息 所以我们在 Activity 的 Destroy 时或者 Stop 时应 该移除消息队列中的消息 更准确的做法如下 public class MainActivity extends AppCompatActivity 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 Override public void handleMessage Message msg MainActivity activity MainActivity reference get if activity null activity mTextView setText Override protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState setContentView R layout activity main mTextView TextView findViewById R id textview loadData private void loadData request Message message Message obtain mHandler sendMessage message Override protected void onDestroy super onDestroy mHandler removeCallbacksAndMessages null 使用 mHandler removeCallbacksAndMessages null 是移除消 息队列中所有消息和所有的 Runnable 当然也可以使用 mHandler removeCallbacks 或 mHandler removeMessages 来 移除指定的 Runnable 和 Message 四 线程造成的内存泄漏四 线程造成的内存泄漏 对于线程造成的内存泄漏 也是平时比较常见的 如下这两个 示例可能每个人都这样写过 test1 new AsyncTask Override protected Void doInBackground Void params SystemClock sleep 10000 return null execute test2 new Thread new Runnable Override public void run SystemClock sleep 10000 start 上面的异步任务和 Runnable 都是一个匿名内部类 因此它们 对当前 Activity 都有一个隐式引用 如果 Activity 在销毁之前 任务 还未完成 那么将导致 Activity 的内存资源无法回收 造成内存泄 漏 正确的做法还是使用静态内部类的方式 如下 static class MyAsyncTask extends AsyncTask private WeakReference weakReference public MyAsyncTask Context context weakReference new WeakReference context Override protected Void doInBackground Void params SystemClock sleep 10000 return nul

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论