在Android开发中,机制是必不可少的,占据着举足轻重的地位,因此作为一位开发者,掌握机制相关的技术是很有必要的。相信很多开发者在面试者或多或少都被问过这方面的问题.Handler 机制算是 Android 基本功,面试常客。但现在面试,多数已经不会直接让你讲讲 Handler 的机制,Looper 是如何循环的,MessageQueue 是如何管理 Message 等,而是基于场景去提问,看看你对 Handler机制的掌握是否扎实。在回答Handler机制时,从Handler的作用开始说起,最后具体到Handler机制在日常开发中的作用,这样的回答理论与实际相结合就比较完善。

在写这篇文章前我不止一次的问自己,网上分析Handler机制原理的文章那么多,为啥还要画蛇添足啊?不是说前人们写的文章不好,我就是觉得他们写的不细,有些点不讲清楚,逻辑很难通顺的,每次我学个什么东西时遇到这种情况都贼难受。我们处在这么一个被层层封装的世界里搞开发,被真相所蒙蔽本来就是一件很痛苦的事,如果分享知识的人再搞出了一堆天书般的“经验总结”,这得多打击求学者的心啊!

设计Handler的初衷

在分析Handler之前,需要先搞清楚两个概念:

1.同步与异步的区别

2.线程与多线程的概念

讲道理上述两点中每个拿出来都涉及到很多东西,一方面我学的也不是很深不好意思献丑另一方面这不是本文重点,所以我就当老铁们都知道啦(嘿嘿一笑)。

Java多线程通信Java中有很多种方法实现线程之间相互通信访问数据,大概先简单的介绍两个典型的,就不上代码了。通过synchronized关键字以“上锁”机制实现线程间的通信。多个线程持有同一个对象,他们可以访问同一个共享变量,利用synchronized“上锁”机制,哪个线程拿到了锁,它就可以对共享变量进行修改,从而实现了通信。使用Object类的wait/notify机制,执行代码obj.wait();后这个对象obj所在的线程进入阻塞状态,直到其他线程调用了obj.notify();方法后线程才会被唤醒。

Android多线程的特殊性

在上面的两个Java多线程通信的方法中都有一个共同的特点,那就是线程的阻塞。利用synchronized机制拿不到锁的线程需要等拿到锁了才会继续执行操作,obj.wait();需要等obj.notify();才会继续执行操作。虽然Android系统是由Java封装的,但是由于Android系统的特殊性,Google的开发人员对Android线程的设计进行了改造。他们把启动APP时运行的主线程定义为UI线程。UI线程负责所有你能想到的所有的跟界面相关的操作,例如分发绘制事件,分发交互事件等可多了。由于其特殊性Android系统强制要求以下两点:为保持用户界面流畅UI线程不能被阻塞,如果线程阻塞界面会卡死,若干秒后Android系统抛出ANR。除UI线程外其他线程不可执行UI操作。

Android多线程通信

既然UI线程中不能被阻塞,那么查询数据库和访问网络这类的耗时操作肯定就不能在UI线程中执行了,我们就需要单独开个线程操作。但是除UI线程外其他线程又不可执行UI操作,最后还是要回到UI线程更新UI,这就需要多线程之间的通信。可Java中线程间通信又都是阻塞式方法,所以传统的Java多线程通信方式在Android中并不适用。为此Google开发人员就不得不设计一套UI线程与Worker线程通信的方法。既能实现多线程之间的通信,又能完美解决UI线程不能被阻塞的问题。具体方法有以下几类:view.post(Runnableaction)系列,通过View对象引用切换回UI线程。activity.runOnUiThread(Runnableaction),通过Activity对象引用切换回UI线程。AsyncTask,内部封装了UI线程与Worker线程切换的操作。Handler,本文的主角,异步消息处理机制,多线程通信。

小结:说到了这里应该大概明白了当初设计Handler的初衷。由于Android系统的特殊性创造了UI线程。由于UI线程的特殊性创造了若干个UI线程与Worker线程通信的方法。在这若干个线程通信方法中就包含了Handler。Handler就是针对Android系统中与UI线程通信而专门设计的多线程通信机

Handler提供的方法有些我们是用不到的,能用到的方法大体分为发送消息,处理消息和切换线程三类。

发送消息类方法

1.sendEmptyMessage

booleansendEmptyMessage(intwhat)

发送一个只有消息标识waht的空消息。该方法适用于不需要传递具体消息只是单独的发通知时。

2.sendEmptyMessageAtTime

booleansendEmptyMessageAtTime(intwhat,longuptimeMillis)

在具体指定的时间uptimeMillis发送一个只有消息标识waht的空消息。

uptimeMillis为系统开机到当前的时间(毫秒)。

3.sendEmptyMessageDelayed

booleansendEmptyMessageDelayed(intwhat,longdelayMillis)

在过了delayMillis毫秒之后发送一个只有消息标识waht的空消息。

4.sendMessage

booleansendMessage(Messagemsg)

发送一条消息。

5.sendMessageAtTime

booleansendMessageAtTime(Messagemsg,longuptimeMillis)

在具体指定的时间uptimeMillis发送一条消息。

uptimeMillis为系统开机到当前的时间(毫秒)。

6.sendMessageDelayed

booleansendMessageDelayed(Messagemsg,longsendMessageDelayed)

在过了delayMillis毫秒之后发送一条消息。

处理消息类方法

handleMessage

voidhandleMessage(Messagemsg)

负责接受消息,所有发送的消息都会返回该方法,注意!必须Override这个方法才能接收消息。

切换线程类方法

1.post

booleanpost(Runnabler)

Runnabler会运行在handler对象被创建的线程上。当我们在UI线程创建了Hnadler对象,在Worker线程调用handler.post()方法时,Runnable就会运行在UI线程中。

2.postAtTime

booleanpostAtTime(Runnabler,longuptimeMillis)

在具体指定的时间uptimeMillis让Runnable运行在Handler对象被创建的线程中。

3.postDelayed

booleanpostDelayed(Runnabler,longdelayMillis)

在具体指定的时间delayMillis之后让Runnable运行在Handler对象被创建的线程中。

好吧,对于Handler就说到这里吧,可能讲的很笼统,因为自己技术能力原因,所以希望大家谅解,也希望大家自己去看视频和书籍或者自己写个小程序加深印象。

分类: 教程分享 标签: 暂无标签

评论

暂无评论数据

暂无评论数据

目录