<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### Handler #### 1、談談消息機制Handler作用 ?有哪些要素 ?流程是怎樣的 ? > * 參考回答: > * 負責**跨線程通信**,這是因為**在主線程不能做耗時操作,而子線程不能更新UI**,所以當子線程中進行耗時操作后需要更新UI時,通過Handler將有關UI的操作切換到主線程中執行。 > * 具體分為四大要素 > * **Message(消息)**:需要被傳遞的消息,消息分為硬件產生的消息(如按鈕、觸摸)和軟件生成的消息。 > * **MessageQueue(消息隊列)**:負責消息的存儲與管理,負責管理由 Handler發送過來的Message。讀取會自動刪除消息,單鏈表維護,插入和刪除上有優勢。在其next()方法中會無限循環,不斷判斷是否有消息,有就返回這條消息并移除。 > * **Handler(消息處理器)**:負責Message的發送及處理。主要向消息池發送各種消息事件(Handler.sendMessage())和處理相應消息事件(Handler.handleMessage()),按照先進先出執行,內部使用的是單鏈表的結構。 > * **Looper(消息池)**:負責關聯線程以及消息的分發,在該線程下從 MessageQueue獲取 Message,分發給Handler,Looper創建的時候會創建一個 MessageQueue,調用loop()方法的時候消息循環開始,其中會不斷調用messageQueue的next()方法,當有消息就處理,否則阻塞在messageQueue的next()方法中。當Looper的quit()被調用的時候會調用messageQueue的quit(),此時next()會返回null,然后loop()方法也就跟著退出。 > * 具體流程如下 > > ![](https://user-gold-cdn.xitu.io/2019/3/11/1696ad811957795d?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) > > * 在主線程創建的時候會創建一個Looper,同時也會在在Looper內部創建一個消息隊列。而在創鍵Handler的時候取出當前線程的Looper,并通過該Looper對象獲得消息隊列,然后Handler在子線程中通過**MessageQueue.enqueueMessage**在消息隊列中添加一條Message。 > * 通過**Looper.loop()** 開啟消息循環不斷輪詢調用 **MessageQueue.next()**,取得對應的Message并且通過**Handler.dispatchMessage**傳遞給Handler,最終調用**Handler.handlerMessage**處理消息。 #### 2、一個線程能否創建多個Handler,Handler跟Looper之間的對應關系 ? > * 參考回答: > * **一個Thread只能有一個Looper,一個MessageQueen,可以有多個Handler** > * **以一個線程為基準,他們的數量級關系是: Thread(1) : Looper(1) : MessageQueue(1) : Handler(N)** #### 3、軟引用跟弱引用的區別 > * 參考回答: > * **軟引用(SoftReference)**:如果一個對象只具有軟引用,則內存空間充足時,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以一直被程序使用。 > * **弱引用(WeakReference)**:如果一個對象只具有弱引用,那么在垃圾回收器線程掃描的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。 > * 兩者之間**根本區別**在于:只具有弱引用的對象擁有更短暫的生命周期,可能隨時被回收。而只具有軟引用的對象只有當內存不夠的時候才被回收,在內存足夠的時候,通常不被回收。 > > ![](https://user-gold-cdn.xitu.io/2019/3/11/1696c45ababaed39?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) > > * 推薦文章: [Java中的四種引用類型:強引用、軟引用、弱引用和虛引用](https://segmentfault.com/a/1190000015282652) #### 4、Handler 引起的內存泄露原因以及最佳解決方案 > * 參考回答: > * 泄露原因: > * Handler 允許我們發送延時消息,如果在延時期間用戶關閉了 Activity,那么該 Activity 會泄露。 這個泄露是因為 Message 會持有 Handler,而又因為 Java 的特性,內部類會持有外部類,使得 Activity 會被 Handler 持有,這樣最終就導致 Activity 泄露。 > * 解決方案: > * **將 Handler 定義成靜態的內部類,在內部持有Activity的弱引用,并在Acitivity的onDestroy()中調用handler.removeCallbacksAndMessages(null)及時移除所有消息。** #### 5、為什么系統不建議在子線程訪問UI? > * 參考回答: > * Android的UI控件不是**線程安全**的,如果在多線程中并發訪問可能會導致UI控件處于不可預期的狀態 > * 這時你可能會問為何系統不對UI控件的訪問加上鎖機制呢?因為 > * 加鎖機制會讓UI訪問邏輯變的復雜 > * 加鎖機制會降低UI的訪問效率,因為加鎖會阻塞某些線程的執行 > > ![](https://user-gold-cdn.xitu.io/2019/3/13/16975fdd364417e0?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) > #### 6、Looper死循環為什么不會導致應用卡死? > * 參考回答: > * 主線程的主要方法就是**消息循環**,一旦退出消息循環,那么你的應用也就退出了,Looer.loop()方法可能會引起主線程的阻塞,但只要它的消息循環沒有被阻塞,能一直處理事件就不會產生ANR異常。 > * 造成**ANR**的不是主線程阻塞,而是主線程的Looper消息處理過程發生了**任務阻塞**,無法響應手勢操作,不能及時刷新UI。 > * **阻塞與程序無響應**沒有必然關系,雖然主線程在沒有消息可處理的時候是阻塞的,但是只要保證有消息的時候能夠立刻處理,程序是不會無響應的。 #### 7、使用Handler的postDealy后消息隊列會有什么變化? > * 參考回答: > * 如果隊列中只有這個消息,那么消息不會被發送,而是計算到時喚醒的時間,先將Looper阻塞,到時間就喚醒它。但如果此時要加入新消息,該消息隊列的對頭跟delay時間相比更長,則插入到頭部,按照觸發時間進行排序,隊頭的時間最小、隊尾的時間最大 #### 8、可以在子線程直接new一個Handler嗎?怎么做? > * 參考回答: > * 不可以,因為在**主線程**中,Activity內部包含一個Looper對象,它會自動管理Looper,處理子線程中發送過來的消息。而對于**子線程**而言,沒有任何對象幫助我們維護Looper對象,所以需要我們自己手動維護。所以要在子線程開啟Handler要先創建Looper,并開啟Looper循環 > > ![](https://user-gold-cdn.xitu.io/2019/3/14/1697b3a7257d670a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) > > * 推薦文章:[Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解](https://blog.csdn.net/guolin_blog/article/details/9991569) #### 9、Message可以如何創建?哪種效果更好,為什么? > * 參考回答:可以通過三種方法創建: > * 直接生成實例**Message m = new Message** > * 通過**Message m = Message.obtain** > * 通過**Message m = mHandler.obtainMessage()** > * 后兩者效果更好,因為Android默認的消息池中消息數量是10,而后兩者是直接在消息池中取出一個Message實例,這樣做就可以避免多生成Message實例。
                  <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>

                              哎呀哎呀视频在线观看