<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ### 10.1 Android的消息機制概述 前面提到,**Android的消息機制主要是指Handler的運行機制以及Handler所附帶的MessageQueue和Looper的工作過程,這三者實際上是一個整體,只不過我們在開發過程中比較多地接觸到Handler而已**。 Handler的主要作用是將一個任務切換到某個指定的線程中去執行,那么Android為什么要提供這個功能呢?或者說Android為什么需要提供在某個具體的線程中執行任務這種功能呢?這是因為**Android規定訪問UI只能在主線程中進行,如果在子線程中訪問UI,那么程序就會拋出異常**。[ViewRootImpl](https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/view/ViewRootImpl.java)對UI操作做了驗證,這個驗證工作是由ViewRootImpl的checkThread方法來完成的,如下所示。 ``` void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } } ``` 針對checkThread方法中拋出的異常信息,相信讀者在開發中都曾經遇到過。**由于這一點的限制,導致必須在主線程中訪問UI,但是Android又建議不要在主線程中進行耗時操作,否則會導致程序無法響應即ANR**。 考慮一種情況,**假如我們需要從服務端拉取一些信息并將其顯示在UI上,這個時候必須在子線程中進行拉取工作,拉取完畢后又不能在子線程中直接訪問UI,如果沒有Handler,那么我們的確沒有辦法將訪問UI的工作切換到主線程中去執行。因此,系統之所以提供Handler,主要原因就是為了解決在子線程中無法訪問UI的矛盾**。 這里再延伸一點, * **系統為什么不允許在子線程中訪問UI呢**? 這是因為**Android的UI控件不是線程安全的,如果在多線程中并發訪問可能會導致UI控件處于不可預期的狀態**, * 那**為什么系統不對UI控件的訪問加上鎖機制呢**? 缺點有兩個: * 首先**加上鎖機制會讓UI訪問的邏輯變得復雜**; * 其次**鎖機制會降低UI訪問的效率,因為鎖機制會阻塞某些線程的執行**。 **鑒于這兩個缺點,最簡單且高效的方法就是采用單線程模型來處理UI操作,對于開發者來說也不是很麻煩,只是需要通過Handler切換一下UI訪問的執行線程即可**。 Handler的使用方法這里就不做介紹了,這里描述一下Handler的工作原理。 **Handler創建時會采用當前線程的Looper來構建內部的消息循環系統,如果當前線程沒有Looper,那么就會報錯**,如下所示。 ``` E/AndroidRuntime(27568): FATAL EXCEPTION: Thread-43484 E/AndroidRuntime(27568): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() E/AndroidRuntime(27568): at android.os.Handler.<init>(Handler.java:121) E/AndroidRuntime(27568): at com.ryg.chapter_10.TestActivity$3.run(TestActivity.java:57) ``` 如何解決上述問題呢?其實很簡單,**只需要為當前線程創建Looper即可,或者在一個有Looper的線程中創建Handler也行**,具體會在10.2.3節中進行介紹。 Handler創建完畢后,這個時候其(線程)內部的Looper以及MessageQueue就可以和Handler一起協同工作了,然后通過Handler的post方法將一個Runnable投遞到Handler內部的Looper中去處理(**這里這樣說其實是不恰當的,Looper其實是運行在創建Handler的線程中的,不能說Looper屬于Handler,一個線程對應一個Looper,一個MessageQueue,但是Handler可以有多個**),也可以通過Handler的send方法發送一個消息,這個消息同樣會在Looper中去處理。**其實post方法最終也是通過send方法來完成的**, 接下來主要來看一下send方法的工作過程。**當Handler的send方法被調用時,它會調用MessageQueue的enqueueMessage方法將這個消息放入消息隊列中,然后Looper發現有新消息到來時,就會處理這個消息,最終消息中的Runnable或者Handler的handleMessage方法就會被調用。注意Looper是運行在創建Handler所在的線程中的,這樣一來Handler中的業務邏輯就被切換到創建Handler所在的線程中去執行了**,這個過程可以用圖10-1來表示。 :-: ![](https://img.kancloud.cn/30/57/3057947d23453017950e3e8b7d2c0e49_1027x603.png) 圖10-1 Handler的工作過程
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看