关于安卓Handler内存泄漏及解决方案

简介: Handler是安卓中常见的实现异步操作的方法,使用简单,但是操作不注意很容易造成内存泄漏。

Handler是安卓中常见的实现异步操作的方法,使用简单,但是操作不注意很容易造成内存泄漏。

在使用Handler的时候,我们常将Handler定义为内部类,也可以单独一个类定义一个Handler,单独定义是不会持有activity引用的,所以不会造成内存泄漏,而在使用内部类的时候,会持有activity的引用,当activity finish掉的使用,Handler仍然持有该activity的引用,这就造成了内存泄漏的原因。

讲讲如何解决Handler定义为内部类所造成内存泄漏的解决方案。

根据官方提示,需要将内部类申明为static 静态内部类,再使用弱引用获取外部类对象。

因为内部类默认持有外部类的引用,就默认持有activity的引用,而静态内部类则不会;而之所以要使用弱引用,只是因为我们需要用到外部类的变量和方法,所以需要一个外部类对象,而使用弱引用的话就不会持有外部类引用。

下面看例子,正常会造成内存泄漏的写法如下:

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
 
        }
    };
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handleroom);
 
        findViewById(R.id.btn_send).setOnClickListener(this);
        tv = findViewById(R.id.tv);
 
        // 延时5min发送一个消息,此时handler是持有activity引用的
        mHandler.sendEmptyMessageDelayed(1, 5 * 60 * 1000);
    }

测试结果可以通过横竖屏切换,然后观察AS控制台内存占用数据即可知晓。

下面是使用static跟弱引用的写法:

  @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handleroom);
        
        findViewById(R.id.btn_send).setOnClickListener(this);
        tv = findViewById(R.id.tv);
 
        MyHandler handler = new MyHandler(this);
        handler.sendEmptyMessageDelayed(0, 5 * 60 * 1000);
    }
 
 
    private static class MyHandler extends Handler {
        private WeakReference<HandlerOOMActivity> weakReference;
        private HandlerOOMActivity activity;
 
        public MyHandler(HandlerOOMActivity activity) {
            weakReference = new WeakReference<>(activity);
            this.activity = activity;
        }
 
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.e(TAG, "handleMessage: ");
            HandlerOOMActivity activity = weakReference.get();
            switch (msg.what) {
                case 0:
                    break;
            }
        }
    }

同样可以观察AS控制台内存占用数据,与未申明为static做对比即可知道。

还有一种请况,Handler在消息处理完后,是会被系统随时回收的,那么即使我们在用内部类的时候,在持有外部类引用的情况下,只要在外部类销毁的时候,让Handler把所有的消息都处理完,即调用Handler的removeCallbacksAndMessages,也是可以避免内存泄漏的。但是一般还是建议采用静态内部类+弱引用的方法。

如何避免Handler引起的内存泄漏,总结三点信息如下:
1、使用static 修饰内部类handler,但是一般会弱引用activity对象,因为要使用activity对象中的成员
2、使用单独定义handler,同样可以弱引用activity
3、可以使用内部类的handler,但是在activity销毁的时候在onDestroy方法中调用Handler的removeCallbacksAndMessages方法

相关文章
|
1月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
41 2
|
1月前
|
存储 前端开发 Java
Android MVVM架构模式下如何避免内存泄漏
Android采用MVVM架构开发项目,如何避免内存泄漏风险?怎样避免内存泄漏?
94 1
|
7天前
|
存储 架构师 Java
内存溢出原因与解决方案(4大主流方案详解)
本文详解内存溢出(OOM)的原因及解决方案。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
内存溢出原因与解决方案(4大主流方案详解)
|
27天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
30天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
48 1
|
1月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
45 2
|
18天前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
1月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
81 7
|
1月前
|
设计模式 Java Android开发
安卓应用开发中的内存泄漏检测与修复
【9月更文挑战第30天】在安卓应用开发过程中,内存泄漏是一个常见而又棘手的问题。它不仅会导致应用运行缓慢,还可能引发应用崩溃,严重影响用户体验。本文将深入探讨如何检测和修复内存泄漏,以提升应用性能和稳定性。我们将通过一个具体的代码示例,展示如何使用Android Studio的Memory Profiler工具来定位内存泄漏,并介绍几种常见的内存泄漏场景及其解决方案。无论你是初学者还是有经验的开发者,这篇文章都将为你提供实用的技巧和方法,帮助你打造更优质的安卓应用。
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台解决方案
【9月更文挑战第27天】在移动应用开发的广阔天地中,安卓和iOS两大操作系统如同双子星座般耀眼。开发者们在这两大平台上追逐着创新的梦想,却也面临着选择的难题。如何在保持高效的同时,实现跨平台的开发?本文将带你探索跨平台开发的魅力所在,揭示其背后的技术原理,并通过实际案例展示其应用场景。无论你是安卓的忠实拥趸,还是iOS的狂热粉丝,这篇文章都将为你打开一扇通往跨平台开发新世界的大门。
下一篇
无影云桌面