Android訊息機制Handler用法

大雄45發表於2022-10-02
導讀 這篇文章介紹了Android訊息機制Handler用法總結,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
1.簡述

Handler訊息機制主要包括: MessageQueue、 Handler、 Looper、Message。

  • Message:需要傳遞的訊息,可以傳遞資料;
  • MessageQueue:訊息佇列,但是它的內部實現並不是用的佇列,而是透過單連結串列的資料結構來維護訊息列表,因為單連結串列在插入和刪除上比較有優勢。主要功能是向訊息池投遞訊息( MessageQueue.enqueueMessage)和取走訊息池的訊息( MessageQueue.next)。
  • Handler:訊息輔助類,主要功能是向訊息池傳送各種訊息事件( Handler.sendMessage)和處理相應訊息事件( Handler.handleMessage);
  • Looper:訊息控制器,不斷迴圈執行( Looper.loop),從MessageQueue中讀取訊息,按分發機制將訊息分發給目標處理者。
2.非同步執行緒切換原理
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();
      }
  }

每一個非同步執行緒,都維護著唯一的一個Looper,每一個Looper會初始化(維護)一個MessageQueue,之後進入一個無限迴圈一直在讀取MessageQueue中儲存的訊息,如果沒有訊息那就一直阻塞等待。

我們在例項化handler的過程中,會先得到當前所線上程的looper物件,之後得到與該looper物件相對應的訊息佇列,看原始碼Handler中持有Looper、MessageQueue。

private static void handleCallback(Message message) {
    message.callback.run();
}
 
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;

當我們傳送訊息的時候,即handler.sendMessage或者handler.post,會將msg中的target賦值為handler自身,這就是實現message從一個執行緒到另外一個執行緒的傳遞的本質,之後加入到訊息佇列中。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

我們一般會重寫handlerMessage方法處理訊息,這將會在msg.target.disPatchMessage方法中被回撥,從而實現了message從一個執行緒到另外一個執行緒的傳遞。

3.總結
  • 1.Handler 的背後有 Looper、MessageQueue 支撐,Looper 負責訊息分發,MessageQueue 負責訊息管理;
  • 2.在建立 Handler 之前一定需要先建立 Looper,Looper 有退出的功能,但是主執行緒的 Looper 不允許退出;
  • 3.非同步執行緒Looper,Looper.prepare()建立Looper,Looper.loop()開始輪詢,需要自己呼叫 Looper.myLooper().quit()退出;
  • 4.Runnable 被封裝進了 Message,可以說是一個特殊的 Message;
  • 5.Handler.handleMessage() 所在的執行緒是 Looper.loop() 方法被呼叫的執行緒;
  • 6.Handler記憶體洩漏的原因

原因:MessageQueue持有Message,Message持有activity,delay多久,message就會持有activity多久。

解決方案:靜態內部類、弱引用,最後不要忘記呼叫Handler.removeCallbacksAndMessages(null)清空所有訊息。

public class SampleActivity extends Activity {
  
  /**
   * Instances of static inner classes do not hold an implicit
   * reference to their outer class.
   */
  private static class MyHandler extends Handler {
    private final WeakReferencemActivity;
  
    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference(activity);
    }
  
    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }
  
 // MyHandler
 private final MyHandler mHandler = new MyHandler(this);
  
  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */ }
  };
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  
    // Post a message and delay its execution for 10 minutes.
    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
     
    // Go back to the previous Activity.
    finish();
  }
  
  @Override
  protected void onDestroy() {
        super.onDestroy();
        //mHandler.removeCallbacksAndMessages(null);
    }
}

原文來自:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2847363/,如需轉載,請註明出處,否則將追究法律責任。

相關文章