异步通信2——AsyncTask详解

482 阅读3分钟

一、 什么是AsyncTask

它本质上就是封装了线程池和handler的异步框架

二、 AsyncTask的使用方法

  1. 三个参数
    • 参数1 Integer 执行AsyncTask时,传入的参数,可在后台任务中使用
    • 参数2 Integer 在后台执行任务时,在界面上显示当前的进度
    • 参数3 String 异步任务执行完成后,如果需要对结果进行返回,使用String作为返回的值
  2. 5个方法
  • onPreExecute
  • doInBackground
  • publishProgress
  • onProgressUpdate
  • onPostExecute
public class UpdateInfoAsyncTask extends AsyncTask<Integer, Integer, String> {

    /**
     * 参数1 Integer 执行AsyncTask时,传入的参数,可在后台任务中使用
     * 参数2 Integer 在后台执行任务时,在界面上显示当前的进度
     * 参数3 String 异步任务执行完成后,如果需要对结果进行返回,使用String作为返回的值
     */

    // 在耗时操作开始前,进行初始化操作,在UI线程中调用,例如显示进度条等
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    // 执行耗时操作,在onPreExecute调用完成后调用,返回执行的结果
    @Override
    protected String doInBackground(Integer... integers) {
        int i;
        for (i = 10; i <= 100; i+=10) {
            // 发布一个进度单位, 可以不断渐变显示后台进行的计算
            publishProgress(i);
        }
        return i + integers[0].intValue() + "";
    }

    // 在主线程中动态显示线程任务执行的进度,在publishProgress后调用
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }


    // 后台计算完成后调用,后台的结果通过String s传递给该方法
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }

}

三、 AsyncTask内部原理

  1. AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行
  2. 线程池的工作线程执行doInBackgroud(mParams)方法执行异步任务
  3. 当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数。

四、 AsyncTask的注意事项

  1. 内存泄漏
    跟Handler的内存泄漏相似,非静态内部类持有外部类的引用,由于activity被销毁,但是AsyncTask还在执行任务,所以此时AsyncTask将持有activity的引用,导致activity想被摧毁时无法被内存回收,引起了内存泄漏。
    解决内存泄漏:弱引用,静态内部类,在activity中的onDestroy中调用asyncTask的cancle方法
  2. 生命周期
    AsyncTask不会随着activity的销毁而销毁,如果没有调用asyncTask的cancle方法,是不会被销毁的。
  3. 结果丢失
    在屏幕旋转或activity由于内存不够被杀掉导致activity重新创建,而之前运行的AsyncTask会持有之前的activity引用, 但是之前的引用已经无效了,所以此时调用AsyncTask的onPostExecute方法去更新界面不会生效。有可能会导致崩溃。
  4. 并行or串行
    在android 1.6 前AsyncTask都是串行,把所有的任务一串一串的放在线程池中有序的进行执行,而在1.6-2.3版本后改成了并行,2.3后又改成了串行。但是还可以调用excute方法可以并行,建议一般情况下只使用串行,这个可以保持整个线程池的稳定。如果并发的话线程池是不稳定的,虽然效率很高。 AsyncTask做不了高并发,太耗时的操作。