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

相关文章
|
iOS开发 编译器 JavaScript
iOS八种内存泄漏问题
循环引用(Retain Cycle) 先简单说一下什么是循环引用(retain cycle) ​假设我们有两个实例A和B,B是A的一个strong型的property,则B的引用计数是1,当A的需要释放的时候,A则会调用[B release]来释放B,B的引用计数则减为0,释放。
2200 0
|
6月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台框架解析
在移动应用开发的广阔舞台上,安卓和iOS一直是两大主角。随着技术的进步,开发者们渴望能有一种方式,让他们的应用能同时在这两大平台上运行,而不必为每一个平台单独编写代码。这就是跨平台框架诞生的背景。本文将探讨几种流行的跨平台框架,包括它们的优势、局限性,以及如何根据项目需求选择合适的框架。我们将从技术的深度和广度两个维度,对这些框架进行比较分析,旨在为开发者提供一个清晰的指南,帮助他们在安卓和iOS的开发旅程中,做出明智的选择。
|
1月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
8月前
|
Android开发 移动开发 小程序
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
|
4月前
|
API Android开发 iOS开发
安卓与iOS开发中的线程管理对比
【9月更文挑战第12天】在移动应用的世界中,安卓和iOS平台各自拥有庞大的用户群体。开发者们在这两个平台上构建应用时,线程管理是他们必须面对的关键挑战之一。本文将深入探讨两大平台在线程管理方面的异同,通过直观的代码示例,揭示它们各自的设计理念和实现方式,帮助读者更好地理解如何在安卓与iOS开发中高效地处理多线程任务。
|
5月前
|
安全 Android开发 iOS开发
探索安卓与iOS开发:异同与未来趋势
在数字时代,安卓和iOS两大移动操作系统引领着全球智能手机市场。本文将深入分析这两个平台的开发环境、用户体验和安全性的异同,并探讨它们面临的挑战与未来的发展趋势。通过比较学习,开发者可以更好地把握跨平台开发的策略,同时预测技术演进的方向。
|
5月前
|
Java Android开发 Swift
安卓与iOS开发:异同与未来趋势
在移动应用开发的广阔天地中,安卓和iOS两大平台各领风骚。本文将深入浅出地探讨这两大系统在开发过程中的异同点,以及它们如何影响开发者的选择和未来的技术走向。从编程语言到用户界面设计,再到市场分布和盈利模式,我们将逐一剖析,为即将踏入或已在这片热土上耕耘的开发者提供一份清晰的指南。
|
5月前
|
IDE 开发工具 Android开发
安卓与iOS开发:平台选择对应用性能的影响
在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。本文将深入探讨这两个平台在开发过程中对应用性能的具体影响,揭示不同选择背后的技术考量。从系统架构到开发工具,从用户体验到市场分布,我们将一探究竟,看看如何在这场平台大战中找到适合自身项目的最优解。
41 0
|
8月前
|
JSON 数据库 Android开发
安卓高级编程技巧:提升应用性能和响应性
【4月更文挑战第13天】本文探讨了提升安卓应用性能和响应性的高级技巧,包括理解性能瓶颈(如过度绘制、内存泄漏、异步任务不当和数据库查询不合理)、优化布局以减少过度绘制、进行内存优化、合理使用多线程、优化数据库操作和高效利用UI线程。通过实例展示了如何改进网络请求的处理,强调了性能优化对用户体验的重要性,并指出随着技术发展,将持续有新工具助力性能提升。
70 7
|
Android开发 C语言
[笔记]安卓 使用breakpad定位崩溃问题
[笔记]安卓 使用breakpad定位崩溃问题
133 0