Android -> 怎样避免Handler引起内存泄露
错误代码
假设在Activiy中通过内部类(Runnable)的方式定义了一个变量runnable,
final Runnable runnable = new Runnable() {
public void run() {
// ... do some work
}
};
handler.postDelayed(runnable, TimeUnit.SECONDS.toMillis(10)
由于Runnable不是static类型,所以会有一个包括Activity实例的implicit reference --- Activity.this。
假设Activity在runnable变量run之前(10s内)被finish掉了可是Activity.this仍然存在。那么Activity的对象就不会被GC回收,从而导致memory leak。
即使使用一个静态内部类,也不能保证万事大吉。
static class MyRunnable implements Runnable {
private View view;
public MyRunnable(View view) {
this.view = view;
}
public void run() {
// ... do something with the view
}
}
如果在runnable运行之前。View被移除了。可是成员变量view还在继续引用它,仍然会导致memory leak。
上面的两个样例其中,导致内存泄露的两种使用方法各自是隐式引用(implicit reference) 和 显式引用(explicit reference)。
解决方法
解决隐式引用的方法比較简单。仅仅要使用内部非静态类(non-static inner class)或者 top-level class(在一个独立的java文件里定义的变量)就能够将隐式变为显式,从而避免内存泄露。
假设继续使用非静态内部类,那么就要在onPause的时候手动结束那些挂起的任务(pending task)。
关于怎样结束不论什么,Handler可參考这篇文章中的Canceling a pending Runnable和Canceling pending Messages。HandlerThread可參考这篇文章。
解决第二个问题要用到WeakReference。WeakReference的使用方法能够google一下。简而言之就是:仅仅要还有其它的stronger reference。WeakReference就能够继续引用。
static class MyRunnable implements Runnable {
private WeakReference>View< view;
public MyRunnable(View view) {
this.view = new WeakReference>View<(view);
}
public void run() {
View v = view.get();
if (v != null) {
// ... do something with the view
}
}
}
这样一来问题就攻克了。美中不足的是每次使用view之前都要做空指针推断。另外一个比較高效的方法就是在onResume中为runnable的view赋值,在onPause中赋值为null。
private static class MyHandler extends Handler {
private TextView view;
public void attach(TextView view) {
this.view = view;
}
public void detach() {
view = null;
}
@Override
public void handleMessage(Message msg) {
// ....
}
总结
在继承Handler或者HandlerThread的时候。
- 尽量定义一个static类或者top-level类。
- 假设用到了ui元素,一定要在Activity的生命周期接触之前释放掉。
參考
Asynchronous Android - Steve Liles
Android -> 怎样避免Handler引起内存泄露的更多相关文章
- Android中使用Handler造成内存泄露的分析和解决
什么是内存泄露?Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向 ...
- Android中使用Handler造成内存泄露
1.什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用 ...
- Android Handler的内存泄露问题+解决方案
谈谈handler的内存泄露问题 再来看看我们的新建Handler的代码: private Handler mHandler = new Handler() { @Override public vo ...
- Android使用Handler造成内存泄露的分析及解决方法
一.什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用 ...
- Android学习系列(37)--App调试内存泄露之Context篇(下)
接着<Android学习系列(36)--App调试内存泄露之Context篇(上)>继续分析. 5. AsyncTask对象 我N年前去盛大面过一次试,当时面试官极力推荐我使用AsyncT ...
- Android中的内部类引起的内存泄露
引子 什么是内部类?什么是内存泄露?为什么Android的内部类容易引起内存泄露?如何解决? 什么是内部类? 什么是内部类?什么又是外部类.匿名类.局部类.顶层类.嵌套类?大家可以参考我这篇文章 ,再 ...
- Android学习系列(36)--App调试内存泄露之Context篇(上)
Context作为最基本的上下文,承载着Activity,Service等最基本组件.当有对象引用到Activity,并不能被回收释放,必将造成大范围的对象无法被回收释放,进而造成内存泄漏. 下面针对 ...
- Android Studio 使用Memory Monitor进行内存泄露分析
在使用Android Studio进行内存泄露分析之前,我们先回顾一下Java相关的内存管理机制,然后再讲述一下内存分析工具如何使用. 一.Java内存管理机制 1. Java内存分配策略 Java ...
- Handler导致内存泄露分析
(非静态)内部类引起内存泄漏的原因 内部类的实现其实是通过编译器的语法糖(Syntactic sugar)实现的,通过生成相应的子类即以OutClassName$InteriorCla ...
随机推荐
- 数据库元数据MetaData
本篇介绍数据库方面的元数据(MetaData)的有关知识.元数据在建立框架和架构方面是特别重要的知识,再下一篇我们仿造开源数据库工具类DbUtils就要使用数据库的元数据来创建自定义JDBC框架. 在 ...
- Effective C++_笔记_条款08_别让异常逃离析构函数
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) C++并不禁止析构函数吐出异常,但它不鼓励你这样做.考虑如下代码 ...
- DLP显示单元(威创)
品牌:威创型号:E-SX675生产商:广东威创视讯科技股份有限公司1.生厂商简介(1)生产商概述广东威创视讯科技股份有限公司(简称威创)成立于2002年,专业从事大屏幕拼接显示产品及其解决方案的研发. ...
- Windows 8 动手实验系列教程 实验8:Windows应用商店API
动手实验 实验 8: Windows应用商店API 2012年9月 简介 编写Windows应用商店应用最令人瞩目的理由之一是您可以方便地将它们发布到Windows应用商店.考虑到世界范围内目前有超过 ...
- Computational Geometry Template
顿时觉得神清气爽!! #include <iostream> #include <math.h> #define eps 1e-8 #define zero(x) (((x)& ...
- bestcoder.hdu.edu.cn
http://bestcoder.hdu.edu.cn/ Problem A 题目链接: http://bestcoder.hdu.edu.cn/contests/contest_showproble ...
- Web API设计
Web API设计经验与总结 在移动互联网的时代, Web服务已经成为了异构系统之间的互联与集成的主要手段,各种 Web服务几乎都采用REST风格的Web Api来构建. 通过Http协议的形式来. ...
- jquery 设置select的默认值
<select id="sel" > <option value="s1" > aaaa </option> <opt ...
- c/c++ extern “C”
c/c++ extern “C” 常见的样式 extern “C”{ ... } extern "C" return-type func-name(type , type ){} ...
- Ray Through Glasses
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30506#problem/T 题意:给你一束光,问你在一个三层的平面类传递n次的种数: 仔 ...