Android 为啥使用Handler

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 为啥使用Handler相关的知识,希望对你有一定的参考价值。

参考技术A android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化。有关Handler的作用,我们总结为:与其他线程协同工作,接收其他线程的消息并通过接收到的消息更新主UI线程的内容。
我们假设在一个UI界面上面,有一个按钮,当点击这个按钮的时候,会进行网络连接,并把网络上的一个字符串拿下来显示到界面上的一个
TextView上面,这时就出现了一个问题,如果这个网络连接的延迟过大,可能是10秒钟甚至更长,那我们的界面将处于一直假死状态,而如果这段时间超
过5秒钟的话,程序会出现异常。
这时我们会想到使用线程来完成以上工作,即当按钮被按下的时候新开启一个线程来完成网络连接工作,并把得到的结果更新到UI上面。但是,这时候又会
出现另一个问题,在Android中,主线程是非线程安全的,也就是说UI的更新只能在本线程中完成,其他线程无法直接对主线程进行操作。
为了解决以上问题,Android设计了Handler机制,由Handler来负责与子线程进行通讯,从而让子线程与主线程之间建立起协作的桥梁,使Android的UI更新的问题得到完美的解决。接下来举例来诠释Handler的基本使用方法。
Handler的工作原理
一般情况下,在主线程中我们绑定了Handler,并在事件触发上面创建新的线程用于完成某些耗时的操作,当子线程中的工作完成之后,会对Handler发送一个完成的信号,而Handler接收到信号后,就进行主UI界面的更新操作。
2
Handler与子线程协作实例
1、创建Handler实现类,在主UI所在类中的内部类
class
MyHandler
extends
Handler

public
MyHandler()


public
MyHandler(Looper
L)

super(L);

//
重写handleMessage方法,接受数据并更新UI
@Override
public
void
handleMessage(Message
msg)

super.handleMessage(msg);
//此处根据msg内容进行UI操作


2、子线程的实现
class
MyThread
implements
Runnable

public
void
run()

Message
msg
=
new
Message();
Bundle
b
=
new
Bundle();
b.putString("cmd",
"update");
msg.setData(b);
MainActivity.this.myHandler.sendMessage(msg);
//通知Handler更新UI


通过以上的两个实现,我们只需要在MainActivity中声明MyHandler实例对象就可以完成线程之间的通讯和界面的更新操作。
MyHandler
myHandler
=
newMyHandler();

Handler的工作原理。为啥在子线程中使用Handler会抛出异常

参考技术A Handler了它在安卓中常见的工作就是子线程与主线程的通信,其实可以直接归类为线程和线程间的通信

谈到Handler会涉及到以下几个类
Handler、Message、Looper、MessageQueue
我们一个一个来说,首先设置场景在一个线程中通知另一个线程

1,创建Looper和创建MessageQueue
首先在一个线程里要用Handler,那么需要准备Looper,调用Looper.prepare(),我们在主线程里面不用准备Looper,那么是因为在我们的主线程中已经给我们初始化好了Looper,
在准备Looper的时候会去校验这个线程中是否存在Looper,如果有Looper那么抛出异常(注意:有一些面试官会问如何判断一个线程中是否存在一个Looper的,它用的是ThreadLocal,它的作用是在线程范围内保证变量的唯一性,Thread中会维护一个类似HashMap的东西,然后用ThreadLocal对象作为key,value就是要存储的变量值,这样就保证了存储数据的唯一性)
如果没有Looper那么new一个Looper,new Looper的同时会new 一个MessageQueue(注意:一个线程中只有一个Looper一个MessageQueue)
然后Looper.loop()就可以启动轮训来轮训消息队列了
2,创建Handler
这个我们在熟悉不过了,继承一个Handler然后复写handlerMessage方法,这里其实面试官也可以问一些比较细致的问题,如下

注意:有面试官会问可以创建几个Handler,我负责任的说是多个,哪个Handler发送的消息哪个Handler处理(吐槽一下有的面试官,你自己把自己要问的问题搞清楚了在去问别人,非要跟我犟只能创建一个)

3,创建Message
Message一般都是使用Message.obtain(),它这里面是有一个spool指向一个Message对象,还有一个next指向下一个Message,它里面维护了一个链表,obtain的时候在表头头取Message,在Message回收的时候在表头添加一个Message,类似栈,默认大小是50
4,消息的处理
Handler对象sendMessage发送消息放入的MessageQueue队列中,Looper轮训到它,然后就开始处理Message,Message会有一个target去记录是哪个Handler发送的它,会调用这个Handler中的dispatchMessage()方法,如果说Message中实现了CallBack那么调用Message中的CallBack,如果Handler中实现了Callback调用Handler中CallBack,否则就都调动Handler中的handleMessage方法

根据上面的原理分析,那就是因为你子线程中没有Looper,给他一个Looper就好了

以上是关于Android 为啥使用Handler的主要内容,如果未能解决你的问题,请参考以下文章

Android 为啥使用Handler

为啥使用 mapview 看不到 android 小吃吧?

Android:何时/为啥我应该使用 FrameLayout 而不是 Fragment?

为啥 Android 使用 pinImages 将可变位图的纹理上传到 GPU?

如果Android经常杀死应用程序,为啥要使用phonegap相机

为啥 Android 的 NumberFormat 使用逗号作为澳大利亚的小数分隔符?