Android Handler源码解析

一.首先看下Handler的常用使用场景

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    Handler mHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                mHandler = new Handler(Looper.myLooper()) {
                    @Override
                    public void handleMessage(@NonNull Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG, "msg.what = " + msg.what);

                    }
                };

                Looper.loop();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = Message.obtain();
                message.what = 200;
                mHandler.sendMessageDelayed(message,1000);
            }
        }).start();
    }

}

在一个子线程中建立Looper和Handler,并且重写handlerMesage()方法,在handlerMessage中接收消息,而这个消息的传递是在另一个子线程中传递过来,之所以能够实现跨线程通信,就在于其它线程拥有了Handler,Handler就像线程出使其它线程的国家大使,有了这个大使,每个线程都能向创立Handler的线程传递信息。

二.源码解析

1.使用Hander前,必须先建立Looper.prepare()方法,先看下prepare的方法

 public static void prepare() {
        prepare(true);
    }
  private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

我们看下sThreadLocal的初始化

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

sThreadLoca是一个静态变量,说明它在Loop类中是唯一的存在,在每个线程中,调用Looper.prepare()方法,最终会在线程没有时Looper,

调用 sThreadLocal.set(new Looper(quitAllowed))方法建立Looper,因为使用类ThreadLocal,这样每个线程只要通过 sThreadLocal.get()方法,就可以获取到该线程的Looper。

既然在线程中建立了Looper,那么我们看下new Looper(quitAllowed)这里初始化了什么,进入源码中

   private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

看到Looper的构造方法中,建立了mQueue队列,这个队列又是什么时候起作用呢。现在先不关心它什么时候起作用,第一步我们明白,Looper.prepare()方法主要就是初始化了Looper和Queue队列。

2.接下里就是Handler的建立了,我们看new Handler(Looper.myLooper())方法

  public Handler(@NonNull Looper looper) {
        this(looper, null, false);
    }
  @UnsupportedAppUsage
    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

我们看到在Handler构造函数中传入了第一步在线程中建立的Looper和Queue,以及新加入的CallBack和标志async,这两个类有什么用呢,我们先不关心,那么第二步这里就知道了建立Handler的时候传入了Looper和队列Queue。

3.接下来看下Loop.loop()方法,我们看下源码

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        // Allow overriding a threshold with a system prop. e.g.
        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        boolean slowDeliveryDetected = false;

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            // Make sure the observer won't change while processing a transaction.
            final Observer observer = sObserver;

            final long traceTag = me.mTraceTag;
            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
            if (thresholdOverride > 0) {
                slowDispatchThresholdMs = thresholdOverride;
                slowDeliveryThresholdMs = thresholdOverride;
            }
            final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
            final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

            final boolean needStartTime = logSlowDelivery || logSlowDispatch;
            final boolean needEndTime = logSlowDispatch;

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

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            Object token = null;
            if (observer != null) {
                token = observer.messageDispatchStarting();
            }
            long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
            try {
                msg.target.dispatchMessage(msg);
                if (observer != null) {
                    observer.messageDispatched(token, msg);
                }
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } catch (Exception exception) {
                if (observer != null) {
                    observer.dispatchingThrewException(token, msg, exception);
                }
                throw exception;
            } finally {
                ThreadLocalWorkSource.restore(origWorkSource);
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (logSlowDelivery) {
                if (slowDeliveryDetected) {
                    if ((dispatchStart - msg.when) <= 10) {
                        Slog.w(TAG, "Drained");
                        slowDeliveryDetected = false;
                    }
                } else {
                    if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                            msg)) {
                        // Once we write a slow delivery log, suppress until the queue drains.
                        slowDeliveryDetected = true;
                    }
                }
            }
            if (logSlowDispatch) {
                showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
            }

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycleUnchecked();
        }
    }

这里虽然很多代码,但主要就是

for (; ; ) {
            Message msg = queue.next();
        ...
            msg.target.dispatchMessage(msg);
        }

我们看到,在这里Looper永久循环,只要队列Queue有数据,则回调msg.targer.dispatchMessage(msg)方法,而msg.targer就是Hander,那么我们看下Hander的dispatchMessage源码,

  public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

可以看到如果我们在在Message中有callback,则调用handlerCallback(msg)方法,如果在我们第二步中Handler初始化设置了Callback,则Callback回调handleMessage(msg)方法,否则默认就走

handlerMessage(msg)方法。这样我们可以总结下,其实Loop.loop()方法就是让在对应线程建立的Loop,不断的循环等待队列的数据,只要有数据,就给Handler回调回Message数据,所以我们接下来要看的就是队列的数据是怎么来的。

4.我们看下在另一个线程中通过Handler传递消息

   new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = Message.obtain();
                message.what = 200;
                mHandler.sendMessageDelayed(message, 1000);
            }
        }).start();

我们看下sendMessageDelayed的源码

  public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
ublic 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);
    }
  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在传递Message的过程中,最终就是通过方法queue.enqueueMessage(msg, uptimeMillis)加入到了队列中去,加入后,触发第三步中Looper调用queue.next()读取数据。这样Handler从发送Message,到Message进入Queue,再到Looper循环读取Queue中的Message,最后Handler中的dispatchMessage就收到了从各个线程传来的Message。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值