Android App 内存泄露之Thread
2015-09-08 23:46
316 查看
Thread 内存泄露
线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。
1.看一下下面是否存在问题
[html] view plaincopy![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
<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引用。 代码如下:
[html] view plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
<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
}
}
}
上面的两个步骤其实是切换两个对象的双向强引用链接
静态内部类:切断Activity 对于 MyThread的强引用。弱引用: 切断MyThread对于Activity 的强引用。
3.AsynTask 内部类会如何呢?
有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重, Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor, 该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的, 因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。
代码如下:
[html] view plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
*
* 弱引用
* @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
}
}
相关文章推荐
- Swift10大开源项目记录
- Unity3D 获得编辑器的Log信息
- 零java基础搞定微信Server_6:微信公众号的文本消息处理
- Unity 3D--外部加载资源AssetBundles
- iOS-runtime-根据类名推送到任意控制器,且实现属性传值
- 5.Android Textview 技巧
- Android_获取手机上SD卡和内存中的可用空间的大小
- iOS分页控制器
- iOS-QQ好友列表实现
- IOS 入门学习记录
- android 数据流量统计
- Android Studio(五):修改Android Studio项目包名
- Android Studio(五):修改Android Studio项目包名
- IOS 绘制背景色渐变的矩形
- IOS真机推送
- Android - View绘图原理总结
- Android--多线程之Handler
- APP开发流程
- PHP学习---如何把富文本编辑器里面的内容生成html 传回给android客户端
- IOS-获取Model(设备型号)、Version(设备版本号)、app(程序版本号)