android asynctask 多线程,Android 多线程:AsyncTask理解和使用总结

de41c082f5c1

AsyncTask目录.png

一、AsyncTask介绍

1.1 作用:

轻量级的异步类,同时方便在子线程更新UI。

1.2 原理:

封装了Handler和两个线程池。AsyncTask的源码链接

线程池THREAD_POOL_EXECUTOR:通过ThreadFactory和一些参数实例化线程池THREAD_POOL_EXECUTOR用于执行任务。

线程池SERIAL_EXECUTOR:内部类SerialExecutor实现Executor也是一个线程池,实例化对象SERIAL_EXECUTOR执行SerialExecutor定义的execute方法来串行(一个一个按顺序)排队任务并使用THREAD_POOL_EXECUTOR来执行任务。

AsyncTask创建时会实例化一个WorkerRunnable对象mWorker和一个FutureTask对象mFuture。FutureTask是一个并发类,充当Runnable的作用。AsyncTask执行任务时把mFuture作为排队线程池SerialExecutor的execute(final Runnable r)的参数传递,接着会串行排队并使用工作线程来处理实际任务。

mFuture对象创建时把mWorker对象作为参数传递,在mFuture在执行任务run()时会调用mWorker的call()方法,因此call()方法是在线程池中进行的。

主线程的Handler:然后call()方法里面接着调用result = doInBackground(mParams);并返回Result对象,这个过程中任务被取消会catch跳出设置AsyncTask结束。call()方法最后postResult(result);获取主线程的Handler发送消息并根据消息类型判定更新UI或者结束AsyncTask。

具体参考:源码解析Android中AsyncTask的工作原理

1.3 参数以及核心函数

AsyncTask是一个泛型类,在android.os包下

de41c082f5c1

AsyncTask类.png

泛型内三个参数定义的是我们需要的数据的类型,如果不需要传递参数,可以用Void来代替,以下是具体含义:

Params:参数的类型;

Progress:后台任务的执行进度类型;

Result:后台任务返回结果的类型。

AsyncTask还提供了4个核心方法:

protected void onPreExecute():在主线程执行,异步任务执行前调用做准备工作;

protected abstract Result doInBackground(Params... var1):在线程池中执行,用于执行异步任务。Params表示异步任务输入参数,可以在此方法中通过publishProgress方法来更新任务进度,publishProgress方法又调用onProgressUpdate方法实现主线程进度更新。这个方法返回Result给onPostExecute方法。

protected void onProgressUpdate(Progress... values):在主线程执行,后台任务执行进度发生变化会调用此方法。

protected void onPostExecute(Result result):在主线程执行,异步任务执行后调用,result参数是由doInBackground返回的。

这四个方法执行的顺序为:onPreExecute(准备)-->doInBackground(后台异步)-->onPostExecute(结果处理)。

还有一个有用的方法:protected void onCancelled():当异步任务取消时调用,而这时候onPostExecute不会被调用。

二、AsyncTask使用

2.1 AsyncTask使用示例:

(1) 创建Activity,布局两个按钮用来开始和取消AsyncTask,一个TextView来显示状态。

android:orientation="vertical" android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/btn_download"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="开始下载"/>

android:id="@+id/btn_cancel"

android:layout_below="@id/btn_download"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="取消下载"/>

android:id="@+id/tv_statue"

android:layout_below="@id/btn_cancel"

android:textSize="15sp"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

(2) 创建内部类自定义MyAsyncTask继承AsyncTask,重写四个主要方法:

//第一个参数:Params参数类型:String类型

//第二个参数:Progress执行进度类型:Object类型

//第三个参数:Result参数类型:Long类型

private class MyAsyncTask extends AsyncTask{

...

@Override

protected void onPreExecute() {...}

@Override

protected Long doInBackground(String... strings) {...}

@Override

protected void onProgressUpdate(Object... values) {...}

@Override

protected void onPostExecute(Long aLong) {...}

@Override //任务取消调用

protected void onCancelled() {...}

(3)开始按钮调用创建MyAsyncTask并执行downloadTask.execute(urls)传入参数。

mDownButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

String[] urls = {

"http://www.jianshu.com/p/d3984e7e204f",

"http://www.jianshu.com/p/8e3cfb87f35e",

"http://www.jianshu.com/p/4fbc2ea2e02b"

};

downloadTask = new MyAsyncTask();

// 这里的url也可以分成一个一个参数传递

downloadTask.execute(urls);

}

});

(4) 取消按钮调用downloadTask.cancel(true)停止MyAsyncTask。

//取消按钮点击事件

downloadTask.cancel(true);

(5) doInBackground(String... strings)方法循环执行下载任务并返回result,是自己定义的二维数组,第一个是字节数,第二个是文章标题。

protected Long doInBackground(String... strings) {

long totalByte = 0;

for (String url:strings){

// downloadFile方法只是一个简单的下载字节流

// 返回的Object[] result是二维数组,一个是下载的字节数,一个是标题

Object[] result = downloadFile(url);

int byteCount = (int) result[0];

totalByte += byteCount;

//传递进度

publishProgress(result);

// 异步任务调用取消则跳出for循环

if(isCancelled()){

break;

}

}

return totalByte;

}

(6) 然后使用publishProgress(result);把数据传递给onProgressUpdate(Object... values)方法来更新UI,这个方法已经切换到了主线程,所以可以更新UI。AsyncTask完成后onPostExecute(Long aLong)方法自动调用再次来更新状态。

@Override

protected void onPostExecute(Long aLong) {...}

看一下效果,源码我会在后面放出,取消下载请自行测试。

de41c082f5c1

AsyncTaskDemo.gif

2.2 AsyncTask使用注意:

AsyncTask的类必须在主线程加载。

AsyncTask的对象必须在主线程创建。

execute方法必须在UI线程调用。

一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则报运行时异常。

在Android1.6之前,AsyncTask是串行执行任务的,Android1.6的时候AsyncTask开始使用线程池处理并行任务,但是从Android3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程串行执行任务。尽管如此,在Android3.0以及后续的版本中,我们仍然可以通过AsyncTask的executeOnExecutor方法来并行地执行任务。

三、AsyncTask优点和缺点

3.1 优点:

简单快捷,使用方便。

UI更新及时,过程可控。

3.2 缺点:

多个异步操作需要更新UI时,就变得麻烦起来。

3.3 其它问题:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值