难以置信(简述handler的机制的原理?)handler的实现原理,handler 机制的原理是什么?,java handler 多线程,
在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就说到这里吧,可能讲的很笼统,因为自己技术能力原因,所以希望大家谅解,也希望大家自己去看视频和书籍或者自己写个小程序加深印象。
本文系作者 @河马 原创发布在河马博客站点。未经许可,禁止转载。
暂无评论数据