关于安卓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方法

相关文章
|
3月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
48 2
|
3月前
|
存储 前端开发 Java
Android MVVM架构模式下如何避免内存泄漏
Android采用MVVM架构开发项目,如何避免内存泄漏风险?怎样避免内存泄漏?
121 1
|
14天前
|
运维 监控 Java
为何内存不够用?微服务改造启动多个Spring Boot的陷阱与解决方案
本文记录并复盘了生产环境中Spring Boot应用内存占用过高的问题及解决过程。系统上线初期运行正常,但随着业务量上升,多个Spring Boot应用共占用了64G内存中的大部分,导致应用假死。通过jps和jmap工具排查发现,原因是运维人员未设置JVM参数,导致默认配置下每个应用占用近12G内存。最终通过调整JVM参数、优化堆内存大小等措施解决了问题。建议在生产环境中合理设置JVM参数,避免资源浪费和性能问题。
37 3
|
2月前
|
存储 架构师 Java
内存溢出原因与解决方案(4大主流方案详解)
本文详解内存溢出(OOM)的原因及解决方案。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
内存溢出原因与解决方案(4大主流方案详解)
|
2月前
|
开发框架 前端开发 Android开发
探索安卓和iOS应用开发中的跨平台解决方案
【10月更文挑战第42天】在移动应用开发的广阔天地中,安卓和iOS系统如同两座巍峨的山峰,分别占据着半壁江山。开发者们在这两座山峰之间穿梭,努力寻找一种既能节省资源又能提高效率的跨平台开发方案。本文将带你走进跨平台开发的世界,探讨各种解决方案的优势与局限,并分享一些实用的代码示例,助你在应用开发的道路上更加游刃有余。
|
3月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
3月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
63 1
|
3月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
73 2
|
2月前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
3月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
102 7

热门文章

最新文章