一般我们都认为,在一个Activity中的AsyncTask它会随着当前Activity的销毁而销毁,但事实并非如此,AsyncTask会在doInBackground()方法执行完毕之后再结束,所有有些猿人在进入到Activity之后快速的离开该页面(前提是在异步中修改页面布局),此时App会很无情的给你Crash,一旦doInBackground()方法执行结束,会依据情况进行下一步的操作。但如果调用了cancle(boolean)方法,则会执行onCanclled(Result)方法,如果没有调用,则自然而然的调用onPostExecute(Result)方法。
说明:cancle(boolean)方法的参数是一个boolean类型的,如果这个值为true,说明当前任务可以打断,调用该方法之后,打断任务,并执行onCanclled(Result)方法,否则,正在执行的任务会继续,知道完成任务为止,再调用onPostExecute(Result)方法。如果在异步任务中有循环操作,我们就需要在循环中通过isCanclled()来进行判断,当前任务是否已经被取消,如果返回true,我们应该避免后续无用的循环操作。但是如果在异步任务中有雷系BitmapFactory.decodeStream()的IO操作,调用cancle方法是无效的,没有意义的,IO流会抛出异常信息,所以不建议使用AsyncTask这个API,可以使用Loader。
言归正传,来讲下AsyncTask的内存泄露的问题,正如上面所说的,他不会随着Activity的销毁而销毁,请看下面的一段示例代码:
package com.tb.demo.utils.hangview;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
/**
* Created by tangbin on 15/9/6.
*/
public class SyncTaskDemoActivity extends Activity {
private int today = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 异步执行任务
new AsyncTask<Object, Void, Boolean>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Object... params) {
// do something in backfround
// 长时间的耗时
while (true) {
today++;
if (today > 100000)
break;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
// success do something
} else {
// error
}
}
}.execute();
}
}
然而,当我们在此异步任务还没有执行完毕的时候去退出当前的这个Activity,此时,这个AsyncTask的生命周期比Activity要长,当Activity销毁的时候,由于该异步任务持有该Activity的引用,导致Activity对象无法进行及时的回收,进而产生内存泄露的问题,而且,当while尚未执行完毕,该循环还有进行,浪费资源。
解决思路:在销毁当前Activity的时候手动去调用AsyncTask的cancle方法
修改后的代码如下:
package com.tb.demo.utils.hangview;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
/**
* Created by tangbin on 15/9/6.
*/
public class SyncTaskDemoActivity extends Activity {
private int today = 0;
private AsyncTask mAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAsyncTask = new AsyncTask<Object, Void, Boolean>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Object... params) {
// do something in backfround
// 长时间的耗时
while (true) {
if (cancel(true))
break;
today++;
if (today > 100000)
break;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
// success do something
} else {
// error
}
}
@Override
protected void onCancelled() {
super.onCancelled();
}
};
// 异步执行任务
mAsyncTask.execute();
}
@Override
protected void onDestroy() {
super.onDestroy();
mAsyncTask.cancel(true);
}
}