返回顶部
首页 > 资讯 > 移动开发 >Android内存泄漏终极解决篇(下)
  • 554
分享到

Android内存泄漏终极解决篇(下)

android内存泄漏Android 2022-06-06 09:06:53 554人浏览 八月长安
摘要

一、概述 在 Android内存泄漏终极解决篇(上)中我们介绍了如何检查一个App是否存在内存泄漏的问题,本篇将总结典型的内存泄漏的代码,并给出对应的解决方案。内存泄漏的主要问

一、概述

Android内存泄漏终极解决篇(上)中我们介绍了如何检查一个App是否存在内存泄漏的问题,本篇将总结典型的内存泄漏的代码,并给出对应的解决方案。内存泄漏的主要问题可以分为以下几种类型:

静态变量引起的内存泄漏 非静态内部类引起的内存泄漏 资源未关闭引起的内存泄漏

二、静态变量引起的内存泄漏

在java中静态变量的生命周期是在类加载时开始,类卸载时结束。换句话说,在android中其生命周期是在进程启动时开始,进程死亡时结束。所以在程序的运行期间,如果进程没有被杀死,静态变量就会一直存在,不会被回收掉。如果静态变量强引用了某个Activity中变量,那么这个Activity就同样也不会被释放,即便是该Activity执行了onDestroy(不要将执行onDestroy和被回收划等号)。这类问题的解决方案为:1.寻找与该静态变量生命周期差不多的替代对象。2.若找不到,将强引用方式改成弱引用。比较典型的例子如下:

单例引起的Context内存泄漏


public class IMManager {
  private Context context;
  private static IMManager mInstance;
  public static IMManager getInstance(Context context) {
    if (mInstance == null) {
      synchronized (IMManager.class) {
        if (mInstance == null)
          mInstance = new IMManager(context);
      }
    }
    return mInstance;
  }
  private IMManager(Context context) {
    this.context = context;
  }
}

当调用getInstance时,如果传入的context是Activity的context。只要这个单例没有被释放,这个Activity也不会被释放。

解决方案
传入Application的context,因为Application的context的生命周期比Activity长,可以理解为Application的context与单例的生命周期一样长,传入它是最合适的。


public class IMManager {
  private Context context;
  private static IMManager mInstance;
  public static IMManager getInstance(Context context) {
    if (mInstance == null) {
      synchronized (IMManager.class) {
        if (mInstance == null)
          //将传入的context转换成Application的context
          mInstance = new IMManager(context.getApplicationContext());
      }
    }
    return mInstance;
  }
  private IMManager(Context context) {
    this.context = context;
  }
}

三、非静态内部类引起的内存泄漏

在java中,创建一个非静态的内部类实例,就会引用它的外围实例。如果这个非静态内部类实例做了一些耗时的操作,就会造成外围对象不会被回收,从而导致内存泄漏。这类问题的解决方案为:1.将内部类变成静态内部类 2.如果有强引用Activity中的属性,则将该属性的引用方式改为弱引用。3.在业务允许的情况下,当Activity执行onDestory时,结束这些耗时任务。

内部线程造成的内存泄漏


public class LeakAty extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    test();
  }
  public void test() {
    //匿名内部类会引用其外围实例LeakAty.this,所以会导致内存泄漏
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }
  }

解决方案
将非静态匿名内部类修改为静态匿名内部类


public class LeakAty extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    test();
  }
  //加上static,变成静态匿名内部类
  public static void test() {
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }
}

Handler引起的内存泄漏


public class LeakAty extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    fetchData();
  }
  private Handler mHandler = new Handler() {
    public void handleMessage(android.os.Message msg) {
      switch (msg.what) {
      case 0:
        // 刷新数据
        break;
      default:
        break;
      }
    };
  };
  private void fetchData() {
    //获取数据
    mHandler.sendEmptyMessage(0);
  }
}

mHandler 为匿名内部类实例,会引用外围对象LeakAty.this,如果该Handler在Activity退出时依然还有消息需要处理,那么这个Activity就不会被回收。

解决方案


public class LeakAty extends Activity {
  private TextView tvResult;
  private MyHandler handler;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    tvResult = (TextView) findViewById(R.id.tvResult);
    handler = new MyHandler(this);
    fetchData();
  }
  //第一步,将Handler改成静态内部类。
  private static class MyHandler extends Handler {
    //第二步,将需要引用Activity的地方,改成弱引用。
    private WeakReference<LeakAty> atyInstance;
    public MyHandler(LeakAty aty) {
      this.atyInstance = new WeakReference<LeakAty>(aty);
    }
    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
      LeakAty aty = atyInstance == null ? null : atyInstance.get();
      //如果Activity被释放回收了,则不处理这些消息
      if (aty == null||aty.isFinishing()) {
        return;
      }
      aty.tvResult.setText("fetch data success");
    }
  }
  private void fetchData() {
    // 获取数据
    handler.sendEmptyMessage(0);
  }
  @Override
  protected void onDestroy() {
    //第三步,在Activity退出的时候移除回调
    super.onDestroy();
    handler.removeCallbacksAndMessages(null);
  }
}

四、资源未关闭引起的内存泄漏

当使用了BraodcastReceiver、Cursor、Bitmap等资源时,当不需要使用时,需要及时释放掉,若没有释放,则会引起内存泄漏。

综上所述,内存泄漏的主要情况为上面的三大类型,最终归结为一点,就是资源在不需要的时候没有被释放掉。所以在编码的过程中要注意这些细节,提高程序的性能。

您可能感兴趣的文章:Android Studio 3.0上分析内存泄漏的原因Android性能优化之利用强大的LeakCanary检测内存泄漏及解决办法Android内存泄漏终极解决篇(上)Android 有效的解决内存泄漏的问题实例详解Android性能优化之利用Rxlifecycle解决RxJava内存泄漏详解Android开发:浅谈MVP模式应用与内存泄漏问题解决浅谈Android应用的内存优化及Handler的内存泄漏问题Android 内存泄漏的几种可能总结详解Android内存泄漏检测与MAT使用Android内存泄漏的轻松解决方法


--结束END--

本文标题: Android内存泄漏终极解决篇(下)

本文链接: https://lsjlt.com/news/25899.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android内存泄漏终极解决篇(下)
    一、概述 在 Android内存泄漏终极解决篇(上)中我们介绍了如何检查一个App是否存在内存泄漏的问题,本篇将总结典型的内存泄漏的代码,并给出对应的解决方案。内存泄漏的主要问...
    99+
    2022-06-06
    android内存泄漏 Android
  • Android内存泄漏终极解决篇(上)
    一、概述 在Android的开发中,经常听到“内存泄漏”这个词。“内存泄漏”就是一个对象已经不需要再使用了,但是因为其它的对象持有该对象的引用,导致它的内存不能被回收。“内存泄...
    99+
    2022-06-06
    android内存泄漏 Android
  • 消除内存泄漏:JavaScript 内存管理的终极指南
    内存泄漏是 JavaScript 中常见的性能问题,会导致 Web 应用程序缓慢、崩溃,甚至完全无响应。理解 JavaScript 内存管理机制对于检测和消除这些泄漏至关重要。本文将深入探讨 JavaScript 内存管理,并提供消除内存...
    99+
    2024-04-02
  • android handler内存泄漏怎么解决
    在Android中,Handler的使用很容易引发内存泄漏问题。以下是一些解决内存泄漏的方法:1. 使用静态内部类:将Handler...
    99+
    2023-09-15
    android
  • PHP 内存泄漏检测:识别和解决内存泄漏
    答案:php 内存泄漏是循环引用引起的,导致应用程序占用内存越来越多。步骤:检测内存泄漏:使用 debug_backtrace()、xdebug 或 php-gc 等工具。实战案例:循环...
    99+
    2024-05-11
    php 内存泄漏 垃圾回收器
  • Android中的内存泄漏
    什么是内存泄漏 长生命周期的对象持有了短生命周期的对象,从而导致短生命周期的对象不能被释放 垃圾回收机制 垃圾回收机制分为:引用计数法、可达性分析法 引用计数法(有循环引用的问...
    99+
    2022-06-06
    内存泄漏 Android
  • android内存溢出和内存泄漏问题怎么解决
    Android内存溢出和内存泄漏是常见的问题,可以通过以下方法来解决:1. 使用内存分析工具:可以使用Android Studio自...
    99+
    2023-08-26
    android
  • tomcat内存泄漏如何解决
    解决Tomcat内存泄漏的方法有以下几种:1. 修复代码:通过检查代码,找到并修复可能引起内存泄漏的问题,例如没有正确关闭资源或者使...
    99+
    2023-08-19
    tomcat
  • java内存泄漏如何解决
    今天小编给大家分享一下java内存泄漏如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1、单例引起的内存泄漏。,由于单...
    99+
    2023-06-30
  • android内存泄漏的解决方式有哪些
    解决Android内存泄漏的方式有以下几种:1. 避免使用静态变量:静态变量的生命周期与应用程序的生命周期相同,如果不及时释放,会导...
    99+
    2023-09-09
    android
  • Android内存泄漏检测-LeakCanary
      前言:   Android内测泄漏是比较常见的问题,在没有造成OOM之前,在测试过程中,也会经常性的忽略这个问题,但在android碎片化严重的,还是存在很多内测泄漏...
    99+
    2022-06-06
    leakcanary android内存泄漏 Android
  • 怎么解决Linux内核内存泄漏
    这篇文章主要讲解了“怎么解决Linux内核内存泄漏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决Linux内核内存泄漏”吧!什么是内存泄漏:程序向系统申请内存,使用完不需要之后,不释...
    99+
    2023-06-15
  • centos下使用jemalloc解决Mysql内存泄漏问题
    参考: MySQL bug:https://bugs.mysql.com/bug.phpid=83047&tdsourcetag=s_pcqq_aiomsg      https://github.com/jemalloc/jemalloc...
    99+
    2023-09-26
    centos mysql linux
  • 怎么解决内存泄漏问题
    本篇内容介绍了“怎么解决内存泄漏问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!问题排查首先确定内存泄漏问题出现的时间,发现在该时间点的上...
    99+
    2023-06-16
  • 一篇文章弄懂javascript内存泄漏
    1、什么是内存泄漏 在了解什么是内存泄漏之前, 我们应该要对内存是什么有个概念, 随机存取存储器(英语:Random Access Memory,缩写:RAM)是与 CPU 直接交...
    99+
    2024-04-02
  • 详解Android Handler 机制 (三)内存泄漏
    ps:看本文之前最好先了解一下Handler源码 常用写法 我们一般使用Handler使用匿名内部类的写法,也就是: private Hand...
    99+
    2022-06-06
    内存泄漏 handler Android
  • Android中常见的内存泄漏
    什么是内存泄漏当一个对象本该被回收,不需要再被使用时,有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,从而产生了内存泄漏。内存泄漏是造成应用程序OOM的主要原因之一,Android...
    99+
    2023-06-04
  • 如何解决JAVA内存泄漏问题
    本篇内容介绍了“如何解决JAVA内存泄漏问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录什么是内存泄漏内存泄漏的原因内存泄漏有哪些情况...
    99+
    2023-06-20
  • drawimage内存泄漏问题怎么解决
    解决drawImage内存泄漏问题的方法如下:1. 及时释放资源:使用完image对象后,可以调用`image = null;`来手...
    99+
    2023-09-05
    drawimage
  • Gomap发生内存泄漏解决方法
    目录正文hamp 结构体代码查看占用的内存数量对于 map 内存泄漏的解法正文 Go 程序运行时,有些场景下会导致进程进入某个“高点”,然后就再也下...
    99+
    2022-11-16
    Go map内存泄漏 Go map
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作