上篇文章介绍了多线程基础内容,这里来讲一讲多线程的表现形式,它有哪些具体的应用。
- AsyncTask
- HandlerThread
- IntentService
一. AsyncTask
1.定义
一个轻量级的异步任务类,是抽象的泛型类,即使用时需实现子类。
public abstract class AsyncTask<Params, Progress, Result> {
...
}
三个泛型参数:
Params:表示执行AsyncTask需要传入的参数的类型。
Progress:表示后台任务执行的进度。
Result:表示后台任务返回的结果的类型。
注意:若没有传递具体的参数,这三个泛型参数都可以使用void
2.作用
(1)实现多线程,在子线程中执行任务,如做耗时操作。
(2)异步通信,消息传递,实现子线程和主线程之间的通信,即将子线程的执行结果传递给主线程,从而在主线程中做相关的UI操作。
3.优点
(1)方便实现异步通信,不需要使用“Thread + Handler”的复杂组合。
(2)节省资源,采用线程池的缓存线程+复用线程,避免了频繁创建线程和销毁线程所带来的系统资源开销。
4.缺点
AsyncTask不太适用于特别耗时的后台任务,而是建议使用线程池。
5.核心方法
(1)onPreExecute():运行在主线程,在异步任务执行之前调用,可做一些初始化操作。
(2)doInBackground(Params… params):运行在子线程,用于处理所有耗时任务,若需更新UI需调用publishProgress(Progress… values)方法。若任务一旦完成,就通过return把任务执行结果返回,如果Result被指定为void,则可不返回执行结果。
(3)onProgressUpdate(Progress… values):运行在主线程,在后台任务中调用publishProgress(Progress… values)之后该方法会被调用。可利用方法中携带的参数如Progress对UI进行更新。
(4)onPostExecute(Result result):运行在主线程,在异步任务执行完毕并通过return语句返回时被调用,可以利用方法中返回的数据对UI进行操作。
(5)onCancelled():运行在主线程,当异步任务被取消时调用。
(6)execute(Params…params):在主线程调用,表示开启一个异步任务。
(7)cancel(boolean mayInterruptIfRunning):在主线程调用,表示停止一个异步任务。
6.自定义AsyncTask
简单模拟一个下载任务,代码如下:
public class TaskActivity extends AppCompatActivity {
private Button startBt;
private TextView text;
private ProgressBar progressBar;
private Button cancelBt;
private DownLoadTask downLoadTask;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task);
startBt = findViewById(R.id.button);
text = findViewById(R.id.text);
progressBar = findViewById(R.id.progress_bar);
cancelBt = findViewById(R.id.cancel);
downLoadTask = new DownLoadTask();
startBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
downLoadTask.execute();
}
});
cancelBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
downLoadTask.cancel(true);
}
});
}
public class DownLoadTask extends AsyncTask<String,Integer,String>{
@Override
protected void onPreExecute() {
super.onPreExecute();
text.setText("加载中...");
}
@Override
protected String doInBackground(String... strings) {
int count = 0;
int length = 1;
while (count < 99){
count += length;
publishProgress(count);
//模拟耗时任务
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
text.setText("loading..."+values[0]+"%");
}
@Override
protected void onPostExecute(String s) {
text.setText("加载完毕");
}
@Override
protected void onCancelled() {
text.setText("取消");
progressBar.setProgress(0);
}
}
}
7.AsyncTask工作原理
(1)内部有一个静态的Handler对象即InternalHandler,通过它来发送任务执行的进度以及执行结束等消息。
(2)内部有两个线程池:
a.SerialExecutor:用于任务的排队,默认的是串行的线程池。
b.THREAD_POOL_EXECUTOR:用于真正处理任务。
(3)排队执行的过程:
a.把参数Params封装成一个FutureTask对象,相当于Runnable。
b.调用SerialExecutor.execute()将FutureTask插入到任务队列tasks。
c.若没有正在执行的AsyncTask任务,则会执行下一个AsyncTask任务,执行完毕后继续执行其他的任务直至所有的任务都执行完成,即默认串行方式执行任务。
二.HandlerThread
HandlerThread是个线程类,它继承Thread类,封装了Handler类,所以与普通的的Thread不同,它具有消息循环的效果。
1.具体实现
(1)实例化一个HandlerThread对象,参数是该线程名称。
(2)通过Handler.start()开启线程。
(3)实例化一个Handler对象并传入HandlerThread中的looper对象,使得与HandlerThread绑定。
(4)通过Handler向消息队列发送消息。
(5)通过HandlerThread.quit()或者HandlerThread.quitSafely()结束线程。
代码示例:
public class HandlerThreadActivity extends AppCompatActivity {
private HandlerThread myHandler;
private String TAG = "HandlerThreadActivity==";
private Handler handler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handlerthread);
//第一步,创建HandlerThread
myHandler = new HandlerThread("myHandler");
//第二步,启动HandlerThread
myHandler.start();
//第三步,创建Handler,并绑定HandlerThread
handler = new Handler(myHandler.getLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
int what = msg.what;
String message = (String) msg.obj;
switch (what) {
case 0:
Log.d(TAG,message);
break;
case 1:
Log.d(TAG,message);
break;
}
}
};
//第四步,主线程发送消息
Message message = new Message();
message.what = 0;
message.obj = "主线程消息";
handler.sendMessage(message);
//子线程发送消息
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 1;
message.obj = "子线程消息";
handler.sendMessage(message);
}
}).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
//第五步,停止HandlerThread
myHandler.quit();
}
}
三.IntentService
IntentService在基础篇Service中做了介绍,这里就不说了。