iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android 中Handler引起的内存泄露
  • 845
分享到

Android 中Handler引起的内存泄露

handlerAndroid 2022-06-06 07:06:50 845人浏览 薄情痞子
摘要

在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用。通常我们的代码会这样实现。 public class SampleActivity ext

Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用。通常我们的代码会这样实现。


public class SampleActivity extends Activity {
 private final Handler mLeakyHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  // ... 
 }
 }
}

但是,其实上面的代码可能导致内存泄露,当你使用Android lint工具的话,会得到这样的警告

In Android, Handler classes should be static or leaks might occur, Messages enqueued on the application thread's MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class

看到这里,可能还是有一些搞不清楚,代码中哪里可能导致内存泄露,又是如何导致内存泄露的呢?那我们就慢慢分析一下。

1.当一个Android应用启动的时候,会自动创建一个供应用主线程使用的Looper实例。Looper的主要工作就是一个一个处理消息队列中的消息对象。在Android中,所有Android框架的事件(比如Activity的生命周期方法调用和按钮点击等)都是放入到消息中,然后加入到Looper要处理的消息队列中,由Looper负责一条一条地进行处理。主线程中的Looper生命周期和当前应用一样长。

2.当一个Handler在主线程进行了初始化之后,我们发送一个target为这个Handler的消息到Looper处理的消息队列时,实际上已经发送的消息已经包含了一个Handler实例的引用,只有这样Looper在处理到这条消息时才可以调用Handler#handleMessage(Message)完成消息的正确处理。

3.在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。静态的内部类不会持有外部类的引用。关于这一内容可以查看细话Java:”失效”的private修饰符

确实上面的代码示例有点难以察觉内存泄露,那么下面的例子就非常明显了


public class SampleActivity extends Activity {
 private final Handler mLeakyHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  // ...
 }
 }
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 // Post a message and delay its execution for 10 minutes.
 mLeakyHandler.postDelayed(new Runnable() {
  @Override
  public void run() {  }
 }, 1000 * 60 * 10);
 // Go back to the previous Activity.
 finish();
 }
}

分析一下上面的代码,当我们执行了Activity的finish方法,被延迟的消息会在被处理之前存在于主线程消息队列中10分钟,而这个消息中又包含了Handler的引用,而Handler是一个匿名内部类的实例,其持有外面的SampleActivity的引用,所以这导致了SampleActivity无法回收,进行导致SampleActivity持有的很多资源都无法回收,这就是我们常说的内存泄露。

注意上面的new Runnable这里也是匿名内部类实现的,同样也会持有SampleActivity的引用,也会阻止SampleActivity被回收。

要解决这种问题,思路就是避免使用非静态内部类,继承Handler时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。注意:一个静态的匿名内部类实例不会持有外部类的引用。 修改后不会导致内存泄露的代码如下


public class SampleActivity extends Activity {
 
 private static class MyHandler extends Handler {
 private final WeakReference<SampleActivity> Mactivity;
 public MyHandler(SampleActivity activity) {
  mActivity = new WeakReference<SampleActivity>(activity);
 }
 @Override
 public void handleMessage(Message msg) {
  SampleActivity activity = mActivity.get();
  if (activity != null) {
  // ...
  }
 }
 }
 private final MyHandler mHandler = new MyHandler(this);
 
 private static final Runnable sRunnable = new Runnable() {
  @Override
  public void run() {  }
 };
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 // Post a message and delay its execution for 10 minutes.
 mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
 // Go back to the previous Activity.
 finish();
 }
}

其实在Android中很多的内存泄露都是由于在Activity中使用了非静态内部类导致的,就像本文提到的一样,所以当我们使用时要非静态内部类时要格外注意,如果其实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露。个人倾向于使用文章的静态类和弱引用的方法解决这种问题。

译文信息

How to Leak a Context: Handlers & Inner Classes

以上就是对Android Handler 引起的内存泄漏资料整理,后续继续补充相关资料,谢谢大家的支持!

您可能感兴趣的文章:浅谈Android应用的内存优化及Handler的内存泄漏问题Android中Handler引起的内存泄露问题解决办法Android 消息机制以及handler的内存泄露解决Android使用Handler造成内存泄露问题Android 优化Handler防止内存泄露Kotlin中的handler如何避免内存泄漏详解


--结束END--

本文标题: Android 中Handler引起的内存泄露

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android中怎么利用Handler防止内存泄露
    今天就跟大家聊聊有关Android中怎么利用Handler防止内存泄露,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 Handler可能导致的内存泄露及其优化 &...
    99+
    2023-05-30
    android handler
  • Android中使用Handler造成的内存泄露如何解决
    这篇文章将为大家详细讲解有关Android中使用Handler造成的内存泄露如何解决,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、什么是内存泄露?  Java使用有向图机制,通过GC自动...
    99+
    2023-05-30
    android handler
  • Java中的substring真的会引起内存泄露么
    这篇文章给大家介绍Java中的substring真的会引起内存泄露么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在Java中开发,String是我们开发程序可以说必须要使用的类型,String有一个substring...
    99+
    2023-06-17
  • ThreadLocal在Tomcat中引起内存泄露怎么解决
    这篇文章主要介绍“ThreadLocal在Tomcat中引起内存泄露怎么解决”,在日常操作中,相信很多人在ThreadLocal在Tomcat中引起内存泄露怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答...
    99+
    2023-06-05
  • Android内存泄露怎么解决
    解决Android内存泄露问题的方法有以下几种:1. 避免长生命周期的引用:确保在不使用时及时释放对象的引用,如Activity中的...
    99+
    2023-09-29
    android
  • android handler内存泄漏怎么解决
    在Android中,Handler的使用很容易引发内存泄漏问题。以下是一些解决内存泄漏的方法:1. 使用静态内部类:将Handler...
    99+
    2023-09-15
    android
  • Android LeakCanary检测内存泄露原理
    目录如何获取context 默认检测哪些类对象的内存泄露 如何将这些生命周期对象纳入监测 ActivityWatcher FragmentAndViewModelWatcher Ro...
    99+
    2024-04-02
  • 内存泄露导致Android 中setVisibility() 失效原理
    目录一、前情概要二、摸索过程1、代码执行了吗?2、视图不显示的直接原因是什么?3、操作的视图是同一个吗?三、解决方案一、前情概要 目前,我在开发的一个 Android 项目需要各个功...
    99+
    2024-04-02
  • 浅谈Node的内存泄露
    目录1、node内存相关知识2、哪些情况会造成内存泄露第一、全局变量第二、函数闭包第三、事件监听3、内存泄露的监测4、Chrome DevTools进行分析和对比5、内存分析的意义1...
    99+
    2024-04-02
  • android内存泄露的根本原因是什么
    Android内存泄漏的根本原因是因为对象在不再使用时未能被垃圾回收器正确地回收,导致内存持续占用和增加。这主要是因为以下几个常见情...
    99+
    2023-09-15
    android
  • android内存泄露怎么查看和解决
    Android内存泄露是指内存中的对象无法被及时释放,导致内存占用过高,影响应用的性能和稳定性。以下是查看和解决Android内存泄...
    99+
    2024-03-13
    android
  • 详解Android内存泄露及优化方案
    目录一、常见的内存泄露应用场景?1、单例的不恰当使用 2、静态变量导致内存泄露 3、非静态内部类导致内存泄露 4、未取消注册或回调导致内存泄露 5、定时器Timer 和 TimerT...
    99+
    2024-04-02
  • 一文搞懂JavaScript中的内存泄露
    目录什么是内存泄漏怎么检测内存泄漏PerformanceMemory内存泄漏的场景垃圾回收算法引用计数循环引用标记清除闭包是内存泄漏吗总结以前我们说的内存泄漏,通常发生在后端,但是不...
    99+
    2024-04-02
  • 内存泄露导致Android中setVisibility()失效怎么解决
    本篇内容介绍了“内存泄露导致Android中setVisibility()失效怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、前情...
    99+
    2023-07-02
  • C++中如何检查内存泄露
    这篇文章给大家介绍C++中如何检查内存泄露,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、前言在Linux平台上 有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器...
    99+
    2023-06-17
  • Android LeakCanary检测内存泄露原理是什么
    小编给大家分享一下Android LeakCanary检测内存泄露原理是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!以LeakCanary2.6源码分析Le...
    99+
    2023-06-14
  • 分析Android常见的内存泄露和解决方案
    目录一、前言二、Android 内存泄露场景2.1、非静态内部类的静态实例2.2、多线程相关的匿名内部类/非静态内部类2.3、Handler 内存泄露2.4、静态 Activity ...
    99+
    2024-04-02
  • 内存泄露的原因是什么
    这篇文章主要介绍“内存泄露的原因是什么”,在日常操作中,相信很多人在内存泄露的原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”内存泄露的原因是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!Th...
    99+
    2023-06-16
  • Android中使用webview时出现内存泄露如何解决
    Android中使用webview时出现内存泄露如何解决,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.避免在xml直接写webview控件,这样会引用activity,...
    99+
    2023-05-31
    android webview
  • c++循环引用导致的内存泄露如何解决
    在 C++ 中,循环引用(circular reference)是指两个或多个对象相互引用,导致内存泄漏的情况。解决循环引用导致的内...
    99+
    2023-10-10
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作