Android App 内存泄露之Thread

Thread 内存泄露

线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。

1.看一下下面是否存在问题


 <span style="white-space:pre">	</span>/**
	 *
	 * @version 1.0.0
	 * @author Abay Zhuang <br/>
	 *		   Create at 2014-7-17
	 */
	public class ThreadActivity extends Activity {
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			new MyThread().start();
		}

		private class MyThread extends Thread {
			@Override
			public void run() {
				super.run();
				dosomthing();
			}
		}
		private void dosomthing(){

		}
	}


这段代码很平常也很简单,是我们经常使用的形式。


真的没有问题吗

我们思考一个问题:假设MyThread的run函数是一个很费时的操作,当我们开启该线程后,将设备的横屏变为了竖屏,
一般情况下当屏幕转换时会重新创建Activity,按照我们的想法,老的Activity应该会被销毁才对,然而事实上并非如此。
由于我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,
MyThread是不会被销毁的,因此它所引用的老的Activity也不会被销毁,因此就出现了内存泄露的问题。

2.这种线程导致的内存泄露问题应该如何解决呢?

  • 第一、将线程的内部类,改为静态内部类。
  • 第二、在线程内部采用弱引用保存Context引用。 代码如下:
    
    
    <span style="white-space:pre">		</span>/**
    		 *
    		 * @version 1.0.0
    		 * @author Abay Zhuang <br/>
    		 *         Create at 2014-7-17
    		 */
    
    		public class ThreadAvoidActivity extends Activity {
    			public void onCreate(Bundle savedInstanceState) {
    				super.onCreate(savedInstanceState);
    				setContentView(R.layout.activity_main);
    				new MyThread(this).start();
    			}
    
    			private void dosomthing() {
    
    			}
    
    			private static class MyThread extends Thread {
    				WeakReference<ThreadAvoidActivity> mThreadActivityRef;
    
    				public MyThread(ThreadAvoidActivity activity) {
    					mThreadActivityRef = new WeakReference<ThreadAvoidActivity>(
    							activity);
    				}
    
    				@Override
    				public void run() {
    					super.run();
    					if (mThreadActivityRef == null)
    						return;
    					if (mThreadActivityRef.get() != null)
    						mThreadActivityRef.get().dosomthing();
    					// dosomthing
    				}
    			}
    		}

    
    
    
    

上面的两个步骤其实是切换两个对象的双向强引用链接

  1. 静态内部类:切断Activity 对于 MyThread的强引用。
  2. 弱引用: 切断MyThread对于Activity 的强引用。

3.AsynTask 内部类会如何呢?

有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,
Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,
该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,
因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。

代码如下:

/**
 *
 * 弱引用
 * @version 1.0.0
 * @author Abay Zhuang <br/>
 *         Create at 2014-7-17
 */
public abstract class WeakAsyncTask<Params, Progress, Result, WeakTarget>
    extends AsyncTask<Params, Progress, Result> {
protected WeakReference<WeakTarget> mTarget;

public WeakAsyncTask(WeakTarget target) {
    mTarget = new WeakReference<WeakTarget>(target);
}

@Override
protected final void onPreExecute() {
    final WeakTarget target = mTarget.get();
    if (target != null) {
        this.onPreExecute(target);
    }
}

@Override
protected final Result doInBackground(Params... params) {
    final WeakTarget target = mTarget.get();
    if (target != null) {
        return this.doInBackground(target, params);
    } else {
        return null;
    }
}

@Override
protected final void onPostExecute(Result result) {
    final WeakTarget target = mTarget.get();
    if (target != null) {
        this.onPostExecute(target, result);
    }
}

protected void onPreExecute(WeakTarget target) {
    // Nodefaultaction
}

protected abstract Result doInBackground(WeakTarget target,
        Params... params);

protected void onPostExecute(WeakTarget target, Result result) {
    // Nodefaultaction
}
}

Android App 内存泄露之Thread,布布扣,bubuko.com

时间: 2024-10-25 22:29:50

Android App 内存泄露之Thread的相关文章

【转载】 Android App 内存泄露之Thread

转载地址http://blog.csdn.net/zhuanglonghai/article/details/37909553 Thread 内存泄露 线程也是造成内存泄露的一个重要的源头.线程产生内存泄露的主要原因在于线程生命周期的不可控. 1.看一下下面是否存在问题 <span style="white-space:pre"> </span>/** * * @version 1.0.0 * @author Abay Zhuang <br/> *

Android App 内存泄露之Handler

Android App 内存泄露之Handler Handler也是造成内存泄露的一个重要的源头,主要Handler属于TLS(Thread Local Storage)变量,生命周期和Activity是不一致的 ,Handler引用Activity会存在内存泄露. 看一下如下代码 /** * * 实现的主要功能. * @version 1.0.0 * @author Abay Zhuang <br/> * Create at 2014-7-28 */ public class Handler

Android App 内存泄露之调试工具(1)

Android App 内存泄露之工具(1) 使用内存监测工具 DDMS –> Heap 操作步骤 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的,没打开的直接Window>ShowView>自己选 将手机通过USB链接至电脑,链接时需要确认手机是处于"USB调试"模式 链接成功后,在DDMS的Devices视图中将会显示手机设备的序列号,以及设备中正在运行的部分进程信息: 点击选中想要监测的进程,如果在进程列表中未出现你

Android 常见内存泄露 &amp; 解决方案

前言 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃 (OOM) 等严重后果. 那什么情况下不能被回收呢? 目前 java 垃圾回收主流算法是虚拟机采用 GC Roots Tracing 算法.算法的基本思路是:通过一系列的名为 GC Roots (GC 根节点)的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径,当一个对象到GC Roots没有任何引用链相连(图论说:从GC Roots

一个给开发者使用的Android App内存清理、监控工具

MemoryMonitor 一个给开发者使用的Android App内存清理.监控工具,可以获取当前手机的内存使用比率,可用内存大小,检查一个APP是否存在内存泄漏. 并且整理了一些优化内存的方式. 0.GitHub地址 https://github.com/cundong/MemoryMonitor 1.内存清理 类似360卫士的 加速球,获取系统已用内存比率.可用内存大小,一键清理. 可以用于测试自己开发的Activity.Fragment健壮性,模拟Activity.Fragment被回收

Android常见内存泄露,学会这六招优化APP性能

很多开发者都知道,在面试的时候会经常被问到内存泄露和内存溢出的问题. 1.内存溢出(Out Of Memory,简称 OOM),通俗理解就是内存不够,即内存占用超出内存的空间大小. 2.内存泄漏(Memory Leak),简单理解就是内存使用完毕之后本该垃圾回收却未被回收. 2 在正式了解内存泄露之前,首先来简单回顾一下 Java 内存分配策略. Java 程序运行时的内存分配策略有三种,分别是静态分配.栈式分配.堆式分配,对应的主要内存空间分别是静态存储区(也称方法区).栈区.堆区. 1.静态

Android中内存泄露与如何有效避免OOM总结

一.关于OOM与内存泄露的概念 我们在Android开发过程中经常会遇到OOM的错误,这是因为我们在APP中没有考虑dalvik虚拟机内存消耗的问题. 1.什么是OOM OOM:即OutOfMemoery,顾名思义就是指内存溢出了.内存溢出是指APP向系统申请超过最大阀值的内存请求,系统不会再分配多余的空间,就会造成OOM error.在我们Android平台下,多数情况是出现在图片不当处理加载的时候. Android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会

Android 字体内存泄露

字体需求 在App开发中,一般都会使用自定义的字体,这些字体美化App的同时,可能还会带来额外的问题,最容易带来的问题就是内存泄露,这里举个实际中遇到的问题作为例子 上面的UI,我们需要在Title.Price上做自定义字体.假如我们这么处理这个需求 Title Typeface tf=Typeface.createFromAsset(getAssets(), Consts.LANTING_FONT_PATH); title.setTypeface(tf); Price Typeface tf=

【转】.. Android应用内存泄露分析、改善经验总结

原文网址:http://wetest.qq.com/lab/view/107.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.194206.TASKID&ADUIN=554147273&ADSESSION=1467939955&ADTAG=CLIENT.QQ.5479_.0&ADPUBNO=26582 前言   通过这几天对好几个应用的内存泄露检测和改善,效果明显: 完全退出应用时,手动触发GC,从原来占有