在Android开发中,我们经常会在子线中进行一次操作,操作完后需要通过Handler传递一些数据给主线程,让主线程完成相应的操作。在这里相信很多同学都会有个疑问,Android中为什么需要用Handler来解决线程更新问题?下面就跟着小编来了解一下Handler机制原理和作用。
Handler 原理
Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。
在android中可以理解为线程间传递消息的处理器。Android程式在启动后会有一个进程,所以的组件都会在这个进程里面运行。刚开始时候,这个进程中只有一个线程,通常叫做UI主线程,这个线程主要负责UI界面的显示更新。但如果要是实现这一个效果的话,就需要单独启动一个子线程来完成。在子线程中完成操作后需要将结果通知到UI主线程后,主线程才会更新UI界面。子线程与UI主线程的通信在android中使用了消息机制来完成,怎么完成的呢?
一般情况下,我们都在主线程中绑定Handler,然后在事件触发上面新建一个子线程用于完成更新的一些操作,当这一操作完成之后就会直接对Handler发送一个信号,信号接收完后,就会对UI界面进行更新。
Handler机制的运行流程主要涉及到四个类:
- Handler:字面意为处理器,负责消息的分发与处理,内部持有一个looper对象和一个MessageQueue对象(MessageQueue对象通过looper对象获得)
- Looper:字面意为循环器,跑在特定的线程里面,持有一个MessageQueue对象,主要通过loop()方法循环地从MessageQueue中来拿到当前线程需要处理的消息并处理。我们通常意义上的切换线程,归根结底就是切换到了这个方法中。为什么需要loop()循环?通常我们开启一个新的线程,当代码执行完线程也就结束了,如果想要该线程做到不断接收并处理外部发来的消息,就需要开启looper
- MessageQueue:消息队列,也就是存放Message的地方,维护了一个通过时间优先级排列的单链表,Handler发出的消息会先存进此队列再被取出执行。
- Message:消息,可携带参数及标识,并持有发送该消息的Handler对象。post(Runnable)方式最后也会被改为Message对象,并将Runnable赋值给Message的callback,处理消息时调用。
一次完整的事件发送与处理流程为:Handler调用sendMessage/post方法,调用其持有的MessageQueue对象的enqueueMessage方法将消息添加到消息队列,looper通过loop()方法会不断的从该MessageQueue中取出Message,并调用Message持有的target(Handler)对象的dispatchMessage方法,进而执行到Handler的handlerMessage或者Runnable的run方法或者额外的callback进行处理。
Handler 作用
如上节所说,我们在子线中完成操作之后需要使用Handler来实现更新主线程的UI界面。这样做的目的主要是因为在android 中的View不是线程安全的。之所以将View设置成非线程安全的,主要是因为以下两点:
- View加锁会增加控件使用的复杂度;
- 会降低控件执行的销量;
Handler的作用不单单只是为了更新主线程UI界面而存在的,准确的讲它其实有两个作用:
- 任务调度:即通过post()和send()等方法来指定某个任务在某个时间执行;
- 线程切换:你也许用过RxJava,但如果在 Android 中使用的话还要配合 RxAndroid,而这里的 RxAndroid 内部就使用 Handler 来实现线程切换。
为什么需要Handler
给大家举个例子,我们在Android的UI开发中,需要经常观察UI界面的变化。这期间当网络延迟比较大的时候,UI界面就处于一直假死的状态,如果这个状态一直持续超过5秒钟的话,程序就会出现异常。
这个时候我们就需要在子线程中操作,这时又会出现一个问题,由于主线程是非线程安全的,UI界面的更新只能在主线程中完成,无法直接利用其他线程对主线程进行操作。
对此为了解决这些问题,就需要用到handler机制,由Handler来负责与子线程进行通讯,从而让子线程与主线程之间建立起协作的桥梁,使Android的UI更新的问题得到完美的解决。
以上内容就是关于Android中为什么需要Handler的详细说明,希望大家有所帮助。
网友评论