Android 消息機制筆記】(android studio)

      網友投稿 1349 2022-05-30

      [Android消息機制(一):概述設計架構](https://www.jianshu.com/p/8656bebc27cb)

      學習Android的消息機制,有幾個設計概念我們必須了解:

      消息:Message

      消息(Message)代表一個行為(what)或者一串動作(Runnable),每一個消息在加入消息隊列時,都有明確的目標(Handler)。

      消息隊列:MessageQueue

      以隊列的形式對外提供插入和刪除的工作,其內部結構是以鏈表的形式存儲消息的。

      Looper

      Looper是循環的意思,它負責從消息隊列中循環的取出消息然后把消息交給目標(Handler)處理。

      Handler

      消息的真正處理者,具備獲取消息、發送消息、處理消息、移除消息等功能。

      線程

      線程,CPU調度資源的基本單位。Android中的消息機制也是基于線程中的概念。

      ThreadLocal

      可以理解為ThreadLocalData,ThreadLocal的作用是提供線程內的局部變量(TLS),這種變量在線程的生命周期內起作用,每一個線程有他自己所屬的值(線程隔離)。

      [Android 消息機制詳解](https://www.jianshu.com/p/3b8c2dbf1124)

      消息機制的流程如下:

      1.準備階段:

      * 在子線程調用 Looper.prepare() 方法或 在主線程調用 Lopper.prepareMainLooper() 方法創建當前線程的 Looper 對象(主線程中這一步由 Android 系統在應用啟動時完成)

      * 在創建 Looper 對象時會創建一個消息隊列 MessageQueue

      * Looper 通過 loop() 方法獲取到當前線程的 Looper 并啟動循環,從 MessageQueue 不斷提取 Message,若 MessageQueue 沒有消息,處于阻塞狀態

      2.發送消息

      * 使用當前線程創建的 Handler 在其它線程通過 sendMessage() 發送 Message 到 MessageQueue

      * MessageQueue 插入新 Message 并喚醒阻塞

      3.獲取消息

      * 重新檢查 MessageQueue 獲取新插入的 Message

      * Looper 獲取到 Message 后,通過 Message 的 target 即 Handler 調用 dispatchMessage(Message msg) 方法分發提取到的 Message,然后回收 Message 并繼續循環獲取下一個 Message

      * Handler 使用 handlerMessage(Message msg) 方法處理 Message

      4.阻塞等待

      * MessageQueue 沒有 Message 時,重新進入阻塞狀態

      [Multi-Threaded Android: Handler, Thread, Looper, and Message Queue](https://medium.com/better-programming/a-detailed-story-about-handler-thread-looper-message-queue-ac2cd9be0d78)

      [how to use postDelayed() correctly in android studio?](https://stackoverflow.com/questions/42379301/how-to-use-postdelayed-correctly-in-android-studio)

      Android 消息機制【筆記】(android studio)

      [Handler、Thread、HandlerThread三者的區別](https://blog.csdn.net/weixin_41101173/article/details/79687313)

      ①Handler:在android中負責發送和處理消息,通過它可以實現其他支線線程與主線程之間的消息通訊。

      ②Thread:Java進程中執行運算的最小單位,亦即執行處理機調度的基本單位。某一進程中一路單獨運行的程序。

      ③HandlerThread:一個繼承自Thread的類HandlerThread,Android中沒有對Java中的Thread進行任何封裝,而是提供了一個繼承自Thread的類HandlerThread類,這個類對Java的Thread做了很多便利的封裝。

      Andriod提供了 Handler ?和 ?Looper ?來滿足線程間的通信。 Handler 先進先出原則。 Looper 類用來管理特定線程內對象之間的消息交換 (MessageExchange) 。

      1)Looper: ?一個線程可以產生一個 Looper 對象,由它來管理此線程里的 MessageQueue( 消息隊列 ) 和對消息進行循環。

      2)Handler: ?你可以構造 Handler 對象來與 Looper 溝通,以便 push 新消息到 MessageQueue 里 ; 或者接收 Looper 從 Message Queue 取出 所送來的消息。

      3) Message Queue( 消息隊列 ): 用來存放線程放入的消息。

      4) Message:是線程間通訊的消息載體。兩個碼頭之間運輸貨物,Message充當集裝箱的功能,里面可以存放任何你想傳遞的消息。

      看到這里就明白了為什么:如果一個線程要處理消息,那么它必須擁有自己的Looper,并不是Handler在哪里創建,就可以在哪里處理消息。

      注:對應關系Thread(1):Looper(1):MessageQueen(1):Handler(n).

      [android之handler切換線程終極篇](https://blog.csdn.net/mysimplelove/article/details/79613361?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control)

      [Handler消息機制詳解,另對于MessageQueue阻塞線程的詳解](https://blog.csdn.net/zip_tts/article/details/86097136?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control)

      用送信的方式來形容如下:

      Handler:收信人/發件人,執行具體的操作/發送消息

      Message:信封,線程發送的消息實體

      MessageQueue:郵筒,消息隊列,存放消息實體

      Looper:送信人,從消息隊列中取消息并進行分發

      至此,Handler,Message,Looper,MessageQueue四者之間的關系已經清晰了:

      Message作為消息載體,用于承載消息。

      MessageQueue作為消息隊列,用于存放消息。

      Looper作為消息傳送的動力,用于獲取分發消息。

      Handler作為消息處理中心,用于處理消息和發送消息。

      [Android HandlerThread詳解](https://blog.csdn.net/VNanyesheshou/article/details/75073307)

      HandlerThread適合處理本地IO讀寫操作(數據庫,文件),因為本地IO操作大多數的耗時屬于毫秒級別,對于單線程 + 異步隊列的形式 不會產生較大的阻塞。而網絡操作相對比較耗時,容易阻塞后面的請求,因此在這個HandlerThread中不適合加入網絡操作。

      [Android 多線程之HandlerThread 完全詳解](https://blog.csdn.net/javazejian/article/details/52426353)

      HandlerThread有那些特點:

      HandlerThread本質上是一個線程類,它繼承了Thread;

      HandlerThread有自己的內部Looper對象,可以進行looper循環;

      通過獲取HandlerThread的looper對象傳遞給Handler對象,可以在handleMessage方法中執行異步任務。

      創建HandlerThread后必須先調用HandlerThread.start()方法,Thread會先調用run方法,創建Looper對象。

      [Decoding Handler and Looper in Android](https://proandroiddev.com/decoding-handler-and-looper-in-android-d4f3f2449513)

      Handler和Looper是主要的底層Android OS之一,幾乎沒有人直接使用(至少在今天)。但是它們是核心,因此許多其他高級解決方案都基于它們。因此,應該知道Handler和Looper是什么,以及它們的運行方式。

      Looper是事件循環的抽象(無限循環,它使事件排入隊列),而Handler是將事件放入/移出事件的隊列(由Looper排空)并在處理這些事件時對其進行處理的抽象。

      Message

      Message數據對象. It contains payload of the “message”. 由于可以將其發送到各種Android組件, 因此Message類實現了Parcelable接口(so that it can be put in extras to bundles and intents).

      作為數據對象Message可以在其中包含一些數據。主要是:

      int what —消息代碼,以了解該消息的含義(例如,它代表什么動作)

      int arg1,arg2—簡單的整數基元,用于存儲一些有效載荷值

      Object obj —自定義對象,我們可能會發送

      Runnable callback -我們可能會發送的自定義操作

      注意:消息中并非所有這些項目都是必需的。另外,某些項目彼此排斥。例如,消息有兩種主要類型:1)使用的what消息和使用的消息callback。

      這意味著我們可以在Message內部發送一些操作(使用callback),也可以發送任意消息(使用what)

      Message是公共類,具有公共構造函數以及上述所有字段都是公共的。因此,從技術上講,可以創建消息實例并手動設置所有必需的數據。但是出于性能原因,Message最佳實踐是使用obtain方法從Messages池中獲取已創建的Message實例(目前未使用的),并使用所需數據對其進行初始化。

      用法非常簡單,例如,如果我們想使用what和獲取自定義Message obj,那么我們將編寫:

      val msg = Message.obtain(handler, what, object)

      MessageQueue

      作為名稱狀態的MessageQueue只是消息隊列。這正是Handler在其中放入事件以及Looper正在消耗事件的隊列的實現。

      Looper

      Looper是為某個線程運行消息循環的類。在Java中,我們有線程,我們可以在其中做一些有用的工作。最初,線程沒有事件循環功能,但是我們可以通過將Looper附加到它們來添加此功能。

      Looper有兩種主要方法:prepare和loop。第一種方法prepare-初始化線程并將Looper附加到該線程。第二種方法loop啟動事件循環。

      注意:

      1.應該清楚的是,在將Looper連接到線程之前運行Looper會導致異常。確保prepare在線程內調用了該方法,然后才調用loop。

      2.每個線程只能有一個Looper。這由ThreadLocalLooper類內的對象控制。因此prepare,在同一線程內兩次調用方法也會導致異常。

      在Looper類中quit,我們感興趣的最后一種方法是和quitSafely。這些方法用于停止事件循環。第一個是不安全的,因為它將終止對隊列的處理,并且某些事件可能未被處理。第二個等待,直到所有消息都處理完畢,然后終止,因此稱為安全。

      Handler

      Handler是一個類,它允許您從線程的MessageQueue發送和處理Messages和Runnables。

      基本上,它的工作方式如下:

      1.客戶端初始化Handler和Looper(因此現在可以使用整個基礎結構了)

      2.客戶端向處理程序發送消息

      3.處理程序將消息發布到Looper的MessageQueue

      4.Looper處理MessageQueue中的消息

      5.當準備好處理消息時,Looper將其發送回Handler,后者可以處理消息。

      因此,我們看到Handler做了兩件事:1)發布要放入隊列中的消息,2)處理由Looper處理的消息。

      讓我們分別看每件事。我們將從發布消息開始。

      我們已經知道,基本上有兩種主要的消息類型:what和Runnable。

      為了發送已創建的消息(例如what),我們可以使用sendMessage,sendMessageDelayed和sendMessageAtTime方法。從名稱中可以明顯看出,sendMessage要盡快發送要處理的消息,sendMessageDelayed在超時后sendMessageAtTime發送要處理的消息,并在某個特定時刻發送要處理的消息。很明顯。

      還有一種方法可以直接發布Runnable而無需先為此創建顯式消息。對于這個有post,postDelayed而且postAtTime方法。它們與sendMessageXXX方法的含義相同,不同之處僅在于我們發送的Runnable不是已創建的消息。

      注意:Handler類中還有其他方法可以使您將消息發送到隊列(例如sendEmptyMessage),盡管它們只是我們已經學到的東西的組合,并且是某種捷徑。我強烈建議您查看源代碼或文檔,以了解有關公共API的更多信息。

      為了在Looper處理消息時處理消息,我們可以執行以下兩項操作之一:

      Handler用我們自己的自定義實現和重寫handleMessage方法擴展類

      Handler使用提供自定義的構造函數創建實例Handler.Callback(具有handleMessage方法)

      消息準備就緒后,Looper會將它們發送到這些回調。

      最后但并非最不重要的一點是,Handler不僅可以將消息添加到事件隊列中,還可以將其刪除。對于這種情況,有一些removeMessages方法可以觸發從MessageQueue中刪除滿足某些條件的未處理消息。

      基本上就是關于Handler。如果您感到困惑,請放心,后面的示例中將提供示例,因此希望所有內容都將更加清晰。

      HandlerThread

      HandlerThread只是具有事件循環的線程。這意味著,如果您需要帶有Looper的線程,則無需自己創建它,只需執行即可HandlerThread。

      用法

      在進行示例之前,讓我們快速回顧一下類,它們的作用以及如何進行連接。如果我們需要某個線程內的事件循環,則其基本結構如下:

      您需要有一個線程(它可能是主線程,HandlerThread或您的自定義線程)

      在該線程內部,準備并啟動Looper(線程現在將使用其自己的MessageQueue進行事件循環)

      注:主線程已經初始化了Looper

      從該線程使用Looper創建處理程序(將消息發送到事件循環,然后在處理它們時對其進行處理)

      將消息發送到Handler并在Handler的回調中處理消息

      太酷了,一切聽起來都合乎邏輯,但是我們錯過了一件事:為什么我們需要所有這些東西,我們試圖解決什么問題?

      根據經驗,在以下情況下,Handler非常適合使用:

      安排一些工作在將來的某個時間執行

      使要在與您自己的線程不同的線程上執行的動作排隊(我們將在后面看到,這擴展到向與您自己不同的線程中的線程發送一些動作)

      [How threads work in Android?](https://medium.com/@souravgupta14/how-threads-work-in-android-3a0ba4ca79ae)

      在后臺線程上執行任務時,最困難的部分不是構建線程本身,而是與線程通信。那就是Handler對象進入的地方。

      假設您要查詢數據庫并檢索所有國家列表,則需要告訴后臺線程查詢數據庫,然后將國家列表發送回可以顯示它們的主線程。我們需要做的第一件事是將消息發送到后臺線程,并讓它知道我們想要做什么。我們在主線程上創建一個消息對象,該消息對象將使用Handler發送到后臺線程,然后將消息添加到消息隊列中,并在到達堆棧頂部時執行。數據庫查詢完成后,循環程序將清理消息隊列,然后將查詢數據發送回主線程。

      再次創建另一個消息對象,使用捆綁將數據附加到消息對象,并且主線程處理程序有助于消息從后臺線程到主線程的傳遞。接收到消息后,它將在主線程的消息隊列中移動,并且最終將數據顯示在視圖中。

      您可以使用各種技術在android中創建線程。

      Threads

      Handler Threads

      Async Task

      Thread pool

      [Android- Handlers, Loopers, MessageQueue Basics](https://medium.com/@mr.anmolsehgal/android-handlers-loopers-messagequeue-basics-d56a750df2cc)

      Android體系結構具有主線程AKA UI線程,該線程在每16ms幀后更新一次UI 。無法在此窗口中更新將反映為“滯后”,甚至更糟,如果它持續5秒鐘失敗,則向用戶顯示“應用程序無響應”,表明應用程序崩潰。

      So the basic design follows:

      1. Handler thread can receive messages from other threads.

      2. Handler thread has a looper that reads queue for any new messages.

      3. Handler Thread has a Message Queue where the messages are written by other threads via a handler.

      4. Looper loops until it reads the message, and then it calls the callback function set by the worker thread, within the Handler Thread.

      5. And thread can write to this HandlerThread if it has its looper.

      He can do so by creating a handler(with its looper as param), and then sending messages via this handler.

      6. Looper.getMainLooper() returns the looper for mainThread, which can be passed into the handler to write to the MainThread directly from any other thread.

      [Using HandlerThread in Android](https://medium.com/@frank.tan/using-handlerthread-in-android-46c285936fdd)

      --https://github.com/frank-tan/AndroidMultithreadingBlogs

      Android提供了高級多線程選項,例如AsyncTask和IntentService,可以將長時間運行的阻塞任務卸載到單獨的線程中。HandlerThread是低級別的線程替代方案,因此討論不多。HandlerThread允許您使用單個消息隊列運行工作線程。

      1.您想要一個重量輕的替代方案來運行一些非常簡單的任務,而AsyncTask和IntentService則顯得過大,例如與攝像頭或加速度計進行通信。

      2.您想要在活動或片段的生命周期中執行一些簡短的任務,例如文件或數據庫操作。值得注意的是,Android框架中提供的AsyncQueryHandler類使用HandlerThread來使數據庫CRUD操作異步化。

      3.您需要在工作線程上按順序處理一些簡單的任務。

      要使用HandlerThread,重要的是要了解Android如何管理線程之間傳遞的消息。

      處理程序是 工作線程上的消息處理器。消息是從例如UI線程卸載的數據或工作(可運行)。在Handler上收到消息時,它將消息添加到消息隊列。每個線程只能有一個消息隊列。Looper是一個消息分派器,它一次從Message Queue中獲取一條消息,然后將其分派給Handler進行處理。

      知道消息傳遞的工作原理后,HandlerThread變得非常簡單。在這里,我擴展了HandlerThread類,以允許自定義處理邏輯(休眠并將消息發布到UI線程)。當然,在現實生活中的項目中,您可能會進行文件操作或訪問硬件等。

      * 避免內存泄漏

      1.使用HandlerThread或實際上任何多線程技術時都應注意的一件事是內存泄漏。

      2.避免在活動中使用非靜態內部類。非靜態內部類將隱式引用托管活動,并阻止該活動被破壞。

      如果您確實需要引用該活動,請使用WeakReference。

      * 避免將長時間運行的任務與短時間的任務混合在一起

      因為HandlerThread只有一個消息隊列,并且所有消息都是按順序處理的,所以長時間運行的阻塞任務將使所有短期運行的任務等待。更好的方法是將長時間運行的任務分隔為單獨的HandlerThread或使用其他線程技術。

      [HandlerThread](https://developer.android.com/reference/android/os/HandlerThread)

      [AndroidManifest.xml詳解](https://www.jianshu.com/p/3b5b89d4e154)

      [Android五大UI布局的特有屬性](https://blog.csdn.net/The_king_of_Asia/article/details/53982418)

      軟件開發

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:一文搞懂 Docker 鏡像的常用操作!(一文搞懂傻傻分不清的手機攝像頭CMOS)
      下一篇:excel表格間隔求和的方法教程詳解(excel表格如何間隔求和)
      相關文章
      亚洲人成自拍网站在线观看| 亚洲第一区二区快射影院| 亚洲国产综合在线| 亚洲熟妇av一区二区三区漫画| 亚洲精品无码99在线观看 | 国产av无码专区亚洲av果冻传媒| 国产av无码专区亚洲av毛片搜| 亚洲第一se情网站| 小说专区亚洲春色校园| 国产精品亚洲专区一区| 国产精品亚洲综合一区在线观看| 亚洲AV无码成人网站在线观看 | 亚洲精品综合在线影院| 国产v亚洲v天堂a无| 亚洲av无码国产综合专区| 亚洲乱码在线视频| 亚洲成_人网站图片| 亚洲日本在线电影| 亚洲成a人无码亚洲成www牛牛| 亚洲AV无码一区二区三区牲色| 亚洲国产成人久久综合| 国产亚洲综合视频| 久久精品亚洲男人的天堂| 亚洲一区无码中文字幕| 国产成人A人亚洲精品无码| 亚洲av女电影网| 亚洲最大的视频网站| 亚洲人色大成年网站在线观看| 亚洲jjzzjjzz在线观看| 99999久久久久久亚洲| 亚洲精品无码你懂的| 亚洲国产日韩成人综合天堂 | 国产亚洲精品免费视频播放| 国产亚洲精品无码成人| 亚洲福利在线视频| 亚洲中文字幕在线无码一区二区| 中文无码亚洲精品字幕| 日韩亚洲翔田千里在线| 国产亚洲精aa成人网站| 亚洲av日韩av不卡在线观看| 亚洲精品**中文毛片|