在Android中不允许非UI线程直接对UI进行修改,否则会出错。UI线程就是主线程。Handler的出现就是为了解决子线程安全地更新UI的需求。handler机制中主要包括handler,looper,message,messageQueue等几个关键的类。
重要对象的作用
- Handler: 发送消息、接收消息并且处理消息
- Message: 消息对象本身
- MessageQueue: 消息队列,缓存消息对象,逐个处理
- Looper: 不断循环MessageQueue,若有消息则执行,若无消息则阻塞
Handler机制工作流程图
handler机制工作流程图Handler.sendMessage()
sendMessage讲解Handler.post()
post讲解关键知识详解
- Handler机制的实现是依赖于MessageQueue和Looper。Looper会不断地去遍历MessageQueue是否为空,当不为空的时候则会取出一个Message,去交给handler去处理(handler中处理Message的方法就是我们需要重写handleMessage()方法),当MessageQueue为空时,则Looper会进入休眠状态,直到有其他线程在MessageQueue中放入Message时会被唤醒。
- 当我们在某个线程中new Handler()的时候,在构造方法中其实做的操作就是绑定当前线程的Looper和MessageQueue。需要注意的是MessageQueue和Looper是成对出现的,从源码中可以看出,在Looper的构造方法中也实例化了一个MessageQueue对象。
- 每一个线程只能有一个Looper和一个对应的MessageQueue,而可以同时和多个handler对象进行绑定。在UI线程中,已经创建了Looper和MessageQueue,不需要额外创建。而在自己开辟的子线程中如果需要使用handler,则必须通过Looper.prepare()和Looper.loop()手动创建,否则在new handler的时候会抛出异常。
- handler抛出的消息,最后都有对应的handler进行处理,因为Message对象中有一个用来标示handler的标志位。
- 对于创建一个Message对象,建议使用Message.obtian()方法来创建,因为Message内部维持了一个对象回收池,一些使用完成的Message可以被在再次利用,这样做可以防止创建过多的Message。
- 主线程(UI线程)中创建Looper也是为了防止主线程执行完就退出了,在ActivityThread中有一个继承自Handler的内部类,这是用来接受系统的消息,来在主线程中执行某种操作,直观表现为Activity的回掉接口方法被调用。
AsyncTask讲解
AsyncTask是一个已封装好的轻量级异步类,本质上还是通过Handler来实现异步更新主线程的UI。这是一个抽象类,需要重写doInBackground()方法。这个方法的代码是在一个开辟的子线程中执行。
AsyncTask中的核心方法及执行顺序
核心方法 执行顺序关键知识详解
- AsyncTask的实现是通过两个线程池和handler的联合使用。其中线程池一个用于线程的调度和服用,另一个是用于真正的线程执行。Handler用于实现异步通信。
- 可以通过AsyncTask的execute()方法来开始执行异步任务,但是每一个Task却只能执行一次。
- 重写的方法中只有doInBackgound()方法中的代码是在子线程中,其它的方法都是在主线程中。
网友评论