使用场景
当我们要进行一些耗时操作(比如发送网络请求),这个时候是不能放在UI线程中执行的,容易造成主线程堵塞。
线程和进程
从操作系统上说,进程是系统资源分配和调度的基本单位,而线程是cpu调度的基本单位,线程是进程的执行单元并且它们共享所在进程的资源。
一个进程至少有一个线程,叫单线程程序,而有多个线程的则是多线程程序,这样的话如果有多个任务,前者只能依次执行,而后者可同时执行。
线程的常见用法
第一种:继承Thread父类并重写run()方法
class MyThread extends Thread{
@Overirrde
public void run{
//some logic
}
}
new MyThead().start();
第二种:实现Runnable接口
class MyThread implements Runnable{
@override
public void run(){
//some logic
}
}
new Thread(new MyThread()).start();
//也可以直接使用匿名内部类的方式(常见写法)
new Thread(new Runnable(){
@override
public void run(){
//some logic
}
}).start();
第三种:实现Callable(可获取返回值)
FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
class MyThread implements Callable<Integer> {
@Override
public Integer call() {
//some logic
return 0;
}
}
new Thread(futureTask).start();
//使用futureTask.get()获取子线程的返回结果
使用Handler在子线程中更新UI
上述的run()方法中的代码是执行在子线程的,而安卓却是不允许在子线程中对UI操作,但有时候又必须根据子线程的任务执行来更新UI。
对于这个问题,安卓提供了一套异步消息处理机制来解决:
Handler简介
Handler是安卓SDK中处理消息的核心类,其Runnable与一个线程的MessageQueue(消息队列)关联。它既可以处理主线程与子线程的通信,也可以处理子线程与子线程的通信。
下图是Handler的通信机制
大致的流程是:Handler发送Message对象的消息到MessageQueue,而Looper会一直尝试从消息队列中取出待处理的Message,取出消息就会回调Handler的dispatchMessage()分发消息方法,并将其传递到Handler的handleMessage()方法中。
使用Handler
1.handler.post()
new Thread(new Runnable(){
@override
public void run(){
//耗时操作
new Handler.post(new Runnable(){
@override
public void run{
//更新UI
}
});
}
}).start();
2.handler.sendMessage()
Handler handler=new Handler(){
@override
public void handleMessage(Message msg){
super.handleMessage(msg);
String data=msg.obj.toString();//获取数据
switch(msg.what){ //判断what标志
case 0:
/*
更新UI
*/
break;
case:
……
}
}
}
new Thread(new Runnable(){
@override
public void run(){
//耗时操作
~~Message message=new Message();//创建Message对象~~
Message message=Message.obtain();//从全局池返回一个Message对象,这样可避免上面一句那样对象的重复创建
message.what=0;//设置标志消息
message.obj="some data";//传递数据
handler.sendMessage(message);//发送消息
}
}).start();
AsyncTask的简单使用
为了更加方便在子线程中对UI操作,安卓也提供了如AsyncTask封装好的工具类,其基本原理还是基于异步消息的处理机制,下面是AsyncTask的基本用法:
//AsyncTask是抽象类,须要创建一个类继承
class MyTask extends AsyncTask<1.Params,2.Progress,3.Result>{
@Override
protected void onPreExecute() {
super.onPreExecute();
//此处执行异步处理前的初始化操作
//比如显示进度条对话框
}
//在doInBackground方法中进行异步任务的处理.
@Override
protected Bitmap doInBackground(String... params) {//对应第一个泛型参数
//获取传进来的参数
String url = params[0];
…………
return bitmap;
//返回值传到onPostExecute方法
}
@Override
protected void onProgressUpdate(Progress…) {//对应第2个泛型参数
//利用后台传过来的参数值对UI元素进行更新
//比如进度条的更新
}
}
@Override
protected void onPostExecute(Bitmap result) {//对应第3个泛型参数
//onPostExecute用于UI的更新.此方法的参数为doInBackground方法返回的值.
super.onPostExecute(result);
//更新imageView
imageView.setImageBitmap(result);
}
}
总结来说,就是在 onPreExecute中执行初始化操作,在doInBackground中执行耗时任务,在onProgressUpdate中进行UI的更新操作,最后在onPostExecute中进行加载完成后的收尾工作。