Android AsyncTask导致的内存泄漏

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




  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值