Android多线程-AsyncTask简单使用

通过前几篇文章的学习,我们已经对Android多线程通信有了一定的了解。那么这篇文章我们来讲讲Android系统为我们内置的异步任务类AsyncTask。运用AsyncTask可以让我们只关注于子线程中的耗时操作和更新UI的操作,使用起来会比Handler要简单一些,当然,只是针对一些简单操作,比如网络操作,图片加载,数据获取等等。

简单介绍

首先AsyncTask是一个抽象类,一般我们使用它会定义一个它的子类并复写其方法来使用,先看类定义:

/**
 * Params:启动任务传入参数
 * Progress:任务执行进度值
 * Result:异步任务完成返回值
 */
public abstract class AsyncTask<Params, Progress, Result> {
}

我们需要传入三个泛型,分别是参数、进度和返回值,其中最重要的几个方法有:

/**
 * 主线程中执行,调用execute方法后立即执行
 */
@MainThread
protected void onPreExecute() {
}

/**
 * 工作线程中执行,会在执行完onPreExecute后执行方法
 * @param Params 接受参数
 * @return 返回结果,传递给onPostExecute
 */
@WorkerThread
protected abstract Result doInBackground(Params... params);

/**
 * 主线程执行,在手动调用publishProgress后被自动调用
 * @param values 异步任务进度
 */
@MainThread
protected void onProgressUpdate(Progress... values) {
}

/**
 * 主线程执行,工作任务完成后调用该方法
 * @param result 返回结果
 */
@MainThread
protected void onPostExecute(Result result) {
}

执行顺序是这样的,异步任务调用execute方法后,会立即在UI线程中执行onPreExecute方法,一般我们会在这里面进行一些初始化操作,紧接着会在开启的子线程中调用doInBackground方法进行耗时操作,在耗时操作中如果手动调用了publishProgress方法,系统会自动调用onProgressUpdate方法更新进度,在异步任务执行完毕后,在UI线程调用并将doInBackground的返回值作为参数传递给onPostExecute方法,至此,异步任务完成。

使用实例

下面我们就用一个实际的例子来演示AsyncTask的使用:

class DownloadImageTask extends AsyncTask<String,Void,Bitmap> {

  /**
   * 主线程中执行,调用execute方法后立即执行
   */
  @Override
  protected void onPreExecute() {
    super.onPreExecute();
    pbLoading.setVisibility(View.VISIBLE);
    ivContainer.setImageBitmap(null);
  }

  /**
  * 工作线程中执行,会在执行完onPreExecute后执行方法
  * @param strings 接受参数
  * @return 返回结果,传递给onPostExecute
  */
  @Override
  protected Bitmap doInBackground(String... strings) {
    //下载图片,返回bitmap对象
    String url = strings[0];
    URLConnection connection;
    InputStream inputStream;
    Bitmap result = null;
    try {
      connection = new URL(url).openConnection();
      inputStream = connection.getInputStream();
      BufferedInputStream bis = new BufferedInputStream(inputStream);
      result = BitmapFactory.decodeStream(bis);
      bis.close();
      inputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return result;
  }

  /**
  * 主线程执行,在手动调用publishProgress后被自动调用
  * @param values 异步任务进度
  */
  @Override
  protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);
  }

  /**
  * 主线程执行,工作任务完成后调用该方法
  * @param bitmap 返回结果
  */
  @Override
  protected void onPostExecute(Bitmap bitmap) {
    super.onPostExecute(bitmap);
    pbLoading.setVisibility(View.GONE);
    ivContainer.setImageBitmap(bitmap);
  }
}

很简单的一个下载图片的异步任务,调用方法也很简单:

protected void loadImage(View view) {
  asyncTask = new DownloadImageTask();
  asyncTask.execute(IMAGE_URL);//可以接受多个参数
}

这里千万要留意使用AsyncTask时定义类型不要直接写AsyncTask,直接用其子类的类型,不然会由于泛型的问题导致ClassCastException,我当年在这儿被坑过,运行效果是这样的:

总结一下AsyncTask的注意事项

  • AsyncTask只能在主线程中初始化和执行

  • AsyncTask的四个重要方法都不由程序员调用,且除了doInBackground执行于子线程以外,其他都在主线程中执行

  • 取消AsyncTask的方法是,调用cancle()方法,并在异步任务执行过程中使用isCanceled判断,若为false,则终止任务

  • AsyncTask内部线程池默认使用同步线程池,即一个任务完成后执行下一个任务,若要使用异步线程池,使用asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);

最后还是github地址~
我的个人博客,欢迎来访~

猜你喜欢

转载自blog.csdn.net/xiaomi987/article/details/80052481