Handler类,可以理解为消息/任务处理者,Handler类是为了与其他几个类一起完成Android的消息循环处理过程,是必不可少的一个类。它主要有两个用途:一是为了在将来某个时间点处理一个消息或者执行一个任务;二是将一个任务放入队列,以便它可以在另外的线程中执行。
AsyncTask类,可以理解为异步任务执行者;这个类的设计目的很明确,就是为了“执行一个较为耗时的异步任务(最多几秒钟),然后更新界面”。这种需求本可以使用Handler和Thread来实现,但由于编码较为复杂,因此Android提供了AsyncTask类。
正式开始讨论Handler和AsyncTask之前,有几个Android的规则要再强调一次:
1.只能在UI线程中访问界面;
2.UI线程被阻塞(大概5秒钟)后会导致ANR(Application Not Responding)错误。
因此我们要使用Handler来创建消息循环,或者使用AsyncTask来创建异步任务来进行操作。
一、Handler
我们绝大部分时间只在主线程(也就是UI线程)中使用Handler,此时Handler会默认使用主线程的Looper和Thread。可以这样理解,普通的Android应用一旦运行起来,就会创建主线程和一个主Looper,它们默默的处理着界面消息,这时你new了一个Handler并重载了它的handMessage方法,你的这个Handler对象就加入到消息的处理中来了。
Handler类包含如下方法用于发送、出来消息。
handlerMessage(Message msg):处理消息的方法。该方法通常用于被重写
final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。
final boolean hasMessage(int what,Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息。
多个重载的Message obtainMessage():获取消息。
sendEmptyMessage(int what):发送空消息
final boolean sendEmptyMessageDelayed(int what,long delayMillis):指定多少毫秒之后发送空消息。
final boolean sendMessage(Message msg):立即发送消息
final boolean sendMessageDelayed(Message msg,long delayMillis):指定多少毫秒之后发送消息。
列:在Activity的onCreate方法里代码:
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == 0x1234){
System.out.println(">>>1234>>>>");
}
}
};
new Timer().schedule(new TimerTask(){
@Override
public void run() {
handler.sendEmptyMessage(0x1234);
}
},0,1200);
说明:通过Timer周期性执行指定任务,Handler处理其发送的消息。
final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what == 0x1234){ System.out.println(">>>1234>>>>"); }else if(msg.what == 0x4321){ System.out.println("<<<4321>>>>>"); }else{} } }; Thread thread=new Thread(new Runnable() { @Override public void run() { Message message=new Message(); message.what=0x4321; handler.sendMessage(message); } }); thread.start();
说明:这里是创建了一个Thread类
二、AsyncTask
AsyncTask是一个辅助类,就是为了将Handler、Thread等封装为一个异步执行框架,供Android Coder可以方便的使用。其主要目的是为了“在其他线程中执行一个耗时操作,并随时报告执行进度给UI线程,执行完成后将结果报告给UI线程”。
AsyncTask使用时必须作为基类被扩展,子类至少重载一个方法doInBackground,另一个方法onPostExecute也经常被重载
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承,继承AsyncTask时需要指定如下三个泛型参数。
Params:启动任务执行的输入参数的类型
Progress:后台任务完成的进度值的类型
Result:后台执行任务完成后返回结果的类型。
使用AsyncTask的步骤:
1.创建AsyncTask的子类,并为三个泛型参数指定类型。如果某个泛型参数不需要指定类型,可将它指定为Void。
2.根据需要,实行AsyncTask的如下方法:
doInBackground()
onProgressUpdate
onPreExecute
onPostExecute
3.调用AsyncTask子类的实例的execute开始执行耗时任务。
使用AsyncTask时必须遵守如下规则:
(1)必须在UI线程中创建AsyncTask的实例
(2)必须在UI线程中调用AsyncTask的execute()方法
(3)AsyncTask的onPreExecute(),onPostExecute(Result result)、doInBackground()、onProgressUpdate方法,不应该由程序员代码调用,而是由Android系统负责调用。
(4)每个AsyncTask只能被执行一次,多次调用将会引发异常。
三、Runnable和Thread
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。
在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
1.避免点继承的局限,一个类可以继承多个接口。
2.适合于资源的共享
Runnable接口和Thread之间的联系:
public class Thread extends Object implements Runnable
发现Thread类也是Runnable接口的子类。
Runnable 并不一定是新开一个线程,比如下面的调用方法就是运行在UI主线程中的:
Handler mHandler=new Handler(); mHandler.post(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub } });