Android AsyncTask导致的内存泄漏

来源:互联网 发布:取名软件推荐 编辑:程序博客网 时间:2024/05/17 05:06

一般我们都认为,在一个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);    }}




1 0
原创粉丝点击