日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 消息循环机制--looper handler

發布時間:2025/4/5 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 消息循环机制--looper handler 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Looper類說明

?  Looper?類用來為一個線程跑一個消息循環。

  線程在默認情況下是沒有消息循環與之關聯的,Thread類在run()方法中的內容執行完之后就退出了,即線程做完自己的工作之后就結束了,沒有循環的概念。

  調用Looper類的?prepare()?方法可以為當前線程創建一個消息循環,調用loop()?方法使之處理信息,直到循環結束。

  大多數和消息循環的交互是通過?Handler?類進行的。

?

  下面是一個典型的實現:

class LooperThread extends Thread {public Handler mHandler;public void run() {Looper.prepare();mHandler = new Handler() {public void handleMessage(Message msg) {// process incoming messages here }};Looper.loop();}}

?

Handler類說明  

  Handler類用來發送和處理消息(Message)以及和線程的消息隊列(MessageQueue)關聯的Runnable對象。

  每一個Handler對象都僅和一個線程及這個線程的消息隊列關聯。

  一個特定線程的所有Handler對象都會收到同樣的方法。(這是一個“一對多”的關系)。

?

  當你創建一個新的Handler對象,它會和創建它的這個線程/線程的消息隊列綁定,從那個時刻開始,它將向這個消息隊列傳遞消息和runnable對象,并且當它們從隊列中出來時執行它們。

  Handler主要有兩種用途:

  1.合理調度安排消息和runnable對象,使它們在將來的某個點被執行。

  2.將一個動作入隊安排在非當前線程執行。

?

  調度消息是通過一系列的post方法和sendMessage方法。

  post方法允許你向消息隊列中入隊一些Runnable對象,在它們被接收到的時候會被調用,(實際上post方法也就是將runnable對象包裝在消息里,然后再通過sendMessage方法實現),post方法有:

  post(Runnable?r)

  postAtFrontOfQueue(Runnable?r)

  postAtTime(Runnable?r,?Object?token, long uptimeMillis)

  postAtTime(Runnable?r, long uptimeMillis)

  postDelayed(Runnable?r, long delayMillis)

?

  sendMessage方法允許你入隊一個消息對象(Message),包含一個bundle數據,之后將會被Handler的handleMessage(Message)方法所處理。

  (這個需要你實現一個Handler的子類)。

  sendMessage方法有:

  sendEmptyMessage(int what)

  sendEmptyMessageAtTime(int what, long uptimeMillis)

  sendEmptyMessageDelayed(int what, long delayMillis)

  sendMessage(Message?msg)

  sendMessageAtFrontOfQueue(Message?msg)

  sendMessageAtTime(Message?msg, long uptimeMillis)

  sendMessageDelayed(Message?msg, long delayMillis)

?

  一個線程對應一個Looper,有一個消息隊列,但是可以關聯多個Handlers。

?

UI線程和非UI線程的通信

  當你的應用進程被創建的時候,應用進程的主線程(main thread)就建立一個消息隊列,操縱top級別的應用對象(四大compotents比如activities、broadcast receivers等)和它們創建的任何窗口。

???????? 這個主線程負責向UI組件分發事件(包括繪制事件),也是在這個主線程里,你的應用和Android的UI組件(components from the Android UI toolkit (components from the android.widget and android.view packages))發生交互。

  因為效率的考慮,所有的View和Widget的操作不是線程安全的,所以相關操作強制放在同一個線程,這樣就可以避免多線程帶來的問題。這個線程就是主線程,也即UI線程。

?

  你可以創建自己的線程,通過一個Handler對象和應用的主線程通信。

  如果你將一個Handler和你的UI線程連接,處理消息的代碼就將會在UI線程中執行。

  新線程和UI線程的通信是通過從你的新線程調用和主線程相關的Handler對象的post或者sendMessage方法實現的,給定的Runnable或Message將會在Handler的消息隊列中,并且在合適的時間被處理。

  總的來說,共有5種方式從非UI線程和UI線程通信:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)

  還有就是通過Handler,或者使用AsyncTask。

  具體參見之前的博文:http://www.cnblogs.com/mengdd/p/3418780.html

?

消息循環

  消息處理機制中,消息存放在一個消息隊列中,而線程圍繞這個隊列進入一個無限循環,直到程序退出。

  如果隊列中有消息,線程就會把消息取出來,并分發給相應的Handler進行處理;

  如果隊列中沒有消息,線程就會進入空閑等待狀態,等待下一個消息的到來。

?

Android的主線程循環創建

  Android程序的運行入口點可以認為是android.app.ActivityThread類的main()方法(源碼2.3.3):

public static final void main(String[] args) {// other codes...// 創建主線程循環 Looper.prepareMainLooper();if (sMainThreadHandler == null) {sMainThreadHandler = new Handler();}ActivityThread thread = new ActivityThread();thread.attach(false);// other codes...// 進入當前線程(此時是主線程)消息循環 Looper.loop();// other codes... thread.detach();// other codes...}

?

  這個main()方法里面為程序創建了主線程循環

  Looper類中的主線程創建方法prepareMainLooper()

/*** Initialize the current thread as a looper, marking it as an application's* main looper. The main looper for your application is created by the* Android environment, so you should never need to call this function* yourself. {@link #prepare()}*/public static final void prepareMainLooper() {prepare();setMainLooper(myLooper());// other codes...}

  上面這個方法是專門為創建應用程序的主線程調用的,其他線程都不應該調用這個方法,而應該調用prepare()方法。

  主線程的Looper對象創建好之后會存在Looper類的成員變量mMainLooper里,通過一個get方法可以獲取到:

/*** Returns the application's main looper, which lives in the main thread of* the application.*/public synchronized static final Looper getMainLooper() {return mMainLooper;}

?

  這樣之后,程序中其他線程就可以獲取主線程的消息循環對象,從而和主線程通信。

?

線程創建消息循環:Looper.prepare()

  非主線程創建消息循環時,調用的是Looper類的prepare()方法,其實創建主線程的方法實質也調用了prepare方法:

/*** Initialize the current thread as a looper. This gives you a chance to* create handlers that then reference this looper, before actually starting* the loop. Be sure to call {@link #loop()} after calling this method, and* end it by calling {@link #quit()}.*/public static final void prepare() {if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper());}

?

  這個方法會調用Looper類的私有構造方法,創建Looper類對象。

private Looper() {// 私有構造方法,在prepare()方法里面調用// 創建消息隊列mQueue = new MessageQueue();mRun = true;// 當前線程mThread = Thread.currentThread();}

?

?

進入消息循環:Looper.loop()

  不管是不是主線程,prepare之后需要調用Looper類的loop()方法,可以看作是進入消息循環:

/*** Run the message queue in this thread. Be sure to call {@link #quit()} to* end the loop.*/public static final void loop() {// 進入當前線程的消息循環Looper me = myLooper();MessageQueue queue = me.mQueue;while (true) {// 從隊列中取出消息Message msg = queue.next(); // might blockif (msg != null) {if (msg.target == null) {// No target is a magic identifier for the quit message.return;}// other codes...// 分發消息 msg.target.dispatchMessage(msg);// 消息的target是Handler類型的對象// other codes...// 釋放清理 msg.recycle();}}}

?

?

消息分發和處理——Handler

  前面創建了消息循環,并且進入了這個循環,但是消息隊列中的消息是如何加入和處理的呢?是通過Handler。

Handler構造:

  Handler有幾個構造重載,如果構造時不提供Looper類對象參數,會獲取當前線程的Looper對象,即將當前線程的消息循環作為Handler關聯的消息循環。

  前面說過,不是所有線程都有一個消息循環,所以如果當前線程沒有消息循環,而構造Handler對象時又沒有指定Looper對象,則會拋出一個運行時異常

mLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");}

?

  如果沒有拋出異常,Handler對象構造好之后,它就關聯了相應的Looper實例和消息隊列實例,即完成綁定。

?

消息發送:

  Handler對象的post方法和sendMessage方法本質上都是發送消息的方法(post類方法實質上是調用了sendMessage方法)。

  所謂發送消息就是把消息放入消息隊列中的合適位置,并且把消息的target設置為本Handler對象

  (這里將消息加入隊列,也有一些什么線程喚醒的事兒咱們不深入討論了)。

  可以添加,也就相應地有一些移除方法。

?

消息處理:

  在上面的Looper.loop()方法中,調用了消息對象target(即發送這個消息的Handler對象)的dispatchMessage()方法。

  /*** Handle system messages here.*/public void dispatchMessage(Message msg) {// 首先,處理Message自己的callback,調用其run方法if (msg.callback != null) {handleCallback(msg);}else {// 其次,調用Handler自留的接口對象// 這個成員變量聲明時的注釋如下:/*** Callback interface you can use when instantiating a Handler to* avoid having to implement your own subclass of Handler.*/if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}// 最后,調用handleMessage方法處理消息,Handler類中這個方法為空,子類可以重寫這個方法 handleMessage(msg);}}

?

  Handler類的handleMessage()方法默認實現為空:

/*** Subclasses must implement this to receive messages.*/public void handleMessage(Message msg) {}

?

  上面的代碼中也解釋了為什么一個消息隊列可以關聯很多個Handler對象,因為雖然隊列只有一個,但是消息的target是當時把它加入的Handler對象。

  所以當隊列中的消息處理的時候,也會找到當時送它來的Handler對象,調用其相應的dispatchMessage()方法,進而調用其中的handleMessage()方法或者mCallback成員的handleMessage()方法來進行處理。

?

參考資料

  Handler:http://developer.android.com/reference/android/os/Handler.html

  Looper:http://developer.android.com/reference/android/os/Looper.html

?

  比較好的幾個博文:

  Android應用程序線程消息循環模型分析:http://blog.csdn.net/luoshengyang/article/details/6905587

?  Android應用程序消息處理機制(Looper、Handler)分析:http://blog.csdn.net/luoshengyang/article/details/6817933

  Android的消息隊列模型:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038469.html

  Android中的Handler, Looper, MessageQueue和Thread:http://www.cnblogs.com/xirihanlin/archive/2011/04/11/2012746.html

?

  本博客其他相關博文:

  Android中的UI線程與非UI線程:http://www.cnblogs.com/mengdd/p/3418780.html

?

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的android 消息循环机制--looper handler的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩欧美在线视频观看 | 久久这里只有 | 91蜜桃臀久久一区二区 | 亚洲性图一区二区 | 波多野结衣乳巨码无在线 | 日韩亚洲在线 | 黄色av毛片 | 青青视频免费看 | 黄色aa级片 | 日韩欧美成人免费视频 | 欧美午夜一区二区三区 | 99久久久久久久久 | 人人妻人人澡人人爽人人精品 | www.黄色在线观看 | 神马午夜在线 | 久久久久亚洲 | 天天夜夜久久 | 日本加勒比中文字幕 | 香蕉av777xxx色综合一区 | 色综合五月婷婷 | 亚洲av中文无码乱人伦在线观看 | 少妇av导航 | 日韩一级片网站 | 99久久精品免费看国产交换 | 91精品系列 | 永久免费未满 | 免费人成视频在线播放 | 婷婷久久综合网 | 国产中文在线视频 | 亚洲欧美亚洲 | av最新地址| 黄色香蕉网 | 99九九精品视频 | 激情丁香婷婷 | 亚洲青色在线 | 日韩伦理中文字幕 | 91丝袜视频 | 欧美日韩在线免费 | 午夜剧场在线 | 欧美三级大片 | 校霸被c到爽夹震蛋上课高潮 | 超碰99热| 中文字幕在线一区 | www.欧美激情 | 亚洲激情av在线 | 午夜视频在线免费播放 | 国产精品九九热 | 日韩精品xxxx | 亚洲欧美日韩中文字幕在线观看 | 森泽佳奈中文字幕 | av观看一区 | 亚洲国产视频在线观看 | 成人免费毛片观看 | 偷操| 人妻少妇精品无码专区久久 | 光明影院手机版在线观看免费 | 久久久久久久9999 | 亚洲一级电影 | 天天看片天天操 | 欧美一区二区三区免费 | 成人免费看片' | 四虎精品一区二区三区 | 麻豆午夜 | 中文字幕av影院 | 成人高清在线 | 久久久久久免费精品 | 五月婷婷色综合 | 九九视频在线观看 | 椎名空在线播放 | www日本在线观看 | 成人av在线网站 | 综合色婷婷一区二区亚洲欧美国产 | 日本涩涩网 | 久久久久久久国产精品 | 91jk制服白丝超短裙大长腿 | 国产极品一区二区 | 久久国内视频 | 91精品国产一区二区三区 | 91日日| 国产白袜脚足j棉袜在线观看 | 俺去射| 日本成人在线看 | 都市激情一区 | 欧美xxxx黑人又粗又长密月 | 中日韩精品一区二区三区 | 日日干夜夜草 | 久久中文网| 亚洲成人一区在线观看 | 三级网站在线播放 | 成人性做爰aaa片免费看不忠 | 成年人网站在线观看视频 | 精品一区二区三区蜜桃 | 亚洲黄色小说图片 | 亚洲砖区免费 | 久久成人国产精品入口 | 性久久 | 国产91免费视频 | 国产在线视频你懂的 | 久久久国产精品一区 |