日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Handler機制相關流程

作者:`TooMee` 更新時間: 2022-07-12 編程語言

Handler:發送和接收消息
Looper :輪詢循環消息隊列,一個線程只有一個Looper
Message:消息的實體
MessageQueue:主要是存儲消息和管理消息

創建Looper:

//ActivityThread.java
public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
 		//此處省略代碼
 		//初始化Looper和messagQueue
        Looper.prepareMainLooper();
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //用于循環消息
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
//Looper.java
  public static void prepareMainLooper() {
   	//消息隊列不可以quit
       prepare(false);
       synchronized (Looper.class) {
           if (sMainLooper != null) {
               throw new IllegalStateException("The main Looper has already been prepared.");
           }
           sMainLooper = myLooper();
       }
   }
/**
prepare有兩個重載的方法,主要是看prepare(boolean quitAllowed) 作用是在創建出MessageQueue時后標識消息隊列是否可以被銷毀,
但是在主線程中時不會被銷毀的
*/
 public static void prepare() {
        prepare(true);
    }

 private static void prepare(boolean quitAllowed) {
      //quitAllowed 
 	  //sThreadLocal.get()不為空表示已經創建出Looper
      if (sThreadLocal.get() != null) {
           throw new RuntimeException("Only one Looper may be created per thread");
           //每個線程只能創建出一個Looper
       }
       //這個地方就是創建出Looper,并且存放到sThreadLocal中
       sThreadLocal.set(new Looper(quitAllowed));
 }

MessageQueue創建以及如何綁定Looper

    private Looper(boolean quitAllowed) {
    	//創建MessageQueue
        mQueue = new MessageQueue(quitAllowed);
        //與當前的線程進行綁定
        mThread = Thread.currentThread();
    }
    MessageQueue(boolean quitAllowed) {
    	//quitAllowed表示是隊列是否可以被銷毀,主線程的隊列不可以被銷毀需要傳入false
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();
    }

Looper.looop()

public static void loop() {
        final Looper me = myLooper();//從sThreadLocal中獲取到創建出的looper對象
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        boolean slowDeliveryDetected = false;
        for (;;) {
        	//死循環表示會一直去查詢消息
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                // 隊列里面沒有消息,需要等待MessageQueue發送消息
                return;
            }

            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            try {
                //查詢到消息后,然后會去回調到Handler中的dispatchMessage中
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
		//后面代碼省略......
    }

創建handler

	//常見的Hanlder的創建方式
     Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };
    public Handler(@Nullable Callback callback, boolean async) {
   	    //獲取Looper,這個是從sThreadLocal中獲取到的
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        //創建出消息隊列MessageQueue
        mQueue = mLooper.mQueue;
        //初始化回調
        mCallback = callback;
        mAsynchronous = async;
    }

Looper.myLooper()

Looper.java
	//主要是處理多線程并發的問題
	static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
	
	//獲取對于的Looper對象,必須先要調用prepare()方法進行創建
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

創建Message

Message.java
       1. Message message = new Message();
       2. Message obtain = Message.obtain();
       
       //使用Message.obtain比直接new出來的Message要好,可以避免多次創建,銷毀message對象優化內存和性能的目的
       public static Message obtain() {
       //用來同步,保證線程安全
        synchronized (sPoolSync) {
        	//回收和復用Handler
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

Message與Handler的綁定
創建Message的時候可以通過Message.obtain(Handler h)這個構造函數去綁定,也可以在Handler enqueueMessage中去綁定,所有發送的Message消息都會調用此方法入隊,所以在創建Message的時候可以不去綁定。


private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;//綁定
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

Handler發送消息
Handler發送的消息重載方法很多,但常用的只有兩種。sendMessage(Message)方法通過一系列的重載方法調用如下流程:

 //1.入口
 handler.sendMessage(Message);
 //調用到sendMessage
 public final boolean sendMessage(@NonNull Message msg) {
        return sendMessageDelayed(msg, 0);
 }
//2.調用sendMessageDelayed
 public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
 }

 //3.調用到sendMessageAtTime
 public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
 }

//4.調用到enqueueMessage
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
 }

//5.調用到enqueueMessage
//將消息保存在消息隊列中,最終又Looper取出,交給Handler的dispatchMessage進行處理
 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
       		 //表示此消息隊列已經被放棄了
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            //延遲時間
            msg.when = when;
            //獲取到消息的第一個元素
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                //如果此隊列中頭部元素是null(空的隊列,一般是第一次),或者此消息不是延時的消息,則此消息需要被立即處理,
                //此時會將這個消息作為新的頭部元素,然后判斷如果Looper獲取消息的線程如果是阻塞狀態則喚醒它,讓它立刻去拿消息處理
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
            //如果此消息是延時的消息,則將其添加到隊列中,原理就是鏈表的添加新元素,按照when,也就是延遲的時間來插入的,延遲的時間越長,
            //越靠后,這樣就得到一條有序的延時消息鏈表,取出消息的時候,延遲時間越小的,就被先獲取了.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {//喚醒線程
                nativeWake(mPtr);
            }
        }
        return true;
    }
	
    public void dispatchMessage(@NonNull Message msg) {
   		 //callback在Message的構造方法中初始化和使用
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
            	//最終回調到上層執行handlerMessage方法
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

Handler處理消息
在handlerMessage(Message)方法中,我們就可以拿到Message對象,然后進行處理,整個Handler的流程就結束了

    Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
        	//獲取Message,進行處理
            super.handleMessage(msg);
        }
    };

總結
Handler的大致流程如上步驟。 從handler.sendMassge發送消息到消息隊列MessageQueue,然后調用looper調用到自己loop()函數帶動MessageQueue從而去輪詢MessageQueue里面的每個Message,當Message達到了可以執行的時間的時候開始執行,執行后會調用Message綁定的Handler來處理消息。

原文鏈接:https://blog.csdn.net/qq_42989195/article/details/123191045

欄目分類
最近更新