Android技术知识Android开发Android开发

彻底搞明白Android消息机制

2018-07-20  本文已影响26人  AntDream

Android中的消息机制主要是指Handler的运行机制,而Handler的运行又离不开Looper和MessageQueue。

MessageQueue

//MessageQueue.class
Message next() {
    ...
    for (;;) {
        ...
        synchronized (this) {
            ...
            if (msg != null) {
                if (now < msg.when) {
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // Got a message.
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
                // No more messages.
                nextPollTimeoutMillis = -1;
            }
            ...
        }
        ...
    }
}
//Looper.class
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");
    }
    //将Looper存到当前线程的ThreadLocal中
    sThreadLocal.set(new Looper(quitAllowed));
}

private Looper(boolean quitAllowed) {
    //创建MessageQueue
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}
Message next() {
    ...
    for (;;) {
        ...
        synchronized (this) {
            // Process the quit message now that all pending messages have been handled.
            if (mQuitting) {
                dispose();
                //返回null,退出循环
                return null;
            }
        }
        ...
    }
    ...
}

void quit(boolean safe) {
    ...
    synchronized (this) {
        ...
        //这样MessageQueue就退出循环啦
        mQuitting = true;
        ...
    }
}

Looper

public static void loop() {
    final Looper me = myLooper();
    //调用loop方法前,必须先通过prepare方法创建looper和消息队列MessageQueue
    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();

    for (;;) {
        //调用MessageQueue的next方法取消息,因为next是个无限循环,所以loop方法也会阻塞
        Message msg = queue.next(); // might block
        //只有在调用MessageQueue的quit方法后MessageQueue才会返回null,才会退出循环监听
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }

        ...
        
        try {
            //msg.target就是Handler,这里就是调用Handler的dispatchMessage方法来处理消息。
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

        ...

    }
}

Handler

//Handler.class
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
private static void handleCallback(Message message) {
    message.callback.run();
}
public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}
/**
 * Callback interface you can use when instantiating a Handler to avoid
 * having to implement your own subclass of Handler.
 *
 * @param msg A {@link android.os.Message Message} object
 * @return True if no further handling is desired
 */
public interface Callback {
    public boolean handleMessage(Message msg);
}
private Handler callbackHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {

        return false;
    }
});
//Handler.class
/**
 * Subclasses must implement this to receive messages.
 */
public void handleMessage(Message msg) {
}
private static class MyHandler extends Handler {
    @Override
    public void handleMessage(Message message) {
        switch (message.what) {
            case MESSAGE_TAG:
                Log.d(Thread.currentThread().getName(),"receive message");
                break;
            default:

                break;
        }
    }
}

Handler为什么能切换线程?

一句话总结就是:Handler是线程间共享的一个对象,而Looper则是每个线程私有的。

怎么理解上面的说法呢?
public class HandlerActivity extends Activity {

    public static final int MESSAGE_TAG = 0x01;
    private MyHandler myHandler;

    //通过派生Handler子类的方式创建我们的Handler
    private static class MyHandler extends Handler {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case MESSAGE_TAG:
                    Log.d(Thread.currentThread().getName(),"receive message");
                    break;
                default:

                    break;
            }
        }
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //创建Handler
        myHandler = new MyHandler();

        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = new Message();
                message.what = MESSAGE_TAG;
                //在子线程中调用UI线程创建的myHandler,发送消息
                myHandler.sendMessage(message);
            }
        }).start();
    }
}
//Handler.class
public Handler() {
    this(null, false);
}

public Handler(Callback callback, boolean async) {
    ...
    //获取Looper,如果当前线程没有Looper就会抛异常
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

//Looper.class
//每个线程都有一个自己的ThreadLocal,用于存储当前线程中的数据
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
    //每个线程只能有一个Looper
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    //第一次调用Looper的prepare方法创建Looper时就会将Looper存入当前线程的ThreadLocal中
    sThreadLocal.set(new Looper(quitAllowed));
}
//从当前线程中的ThreadLocal中获取Looper
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}
//Handler.class
public final boolean sendMessage(Message msg)
{
    return sendMessageDelayed(msg, 0);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

public boolean sendMessageAtTime(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(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    //往MessageQueue中插入消息
    return queue.enqueueMessage(msg, uptimeMillis);
}

总结

Handler机制

我们用上面派生Handler的子类的例子来总结下Handler机制

一句话就是:我们在UI线程中创建的Handler,里面用的Looper是UI线程的。当我们在子线程中调用sendMessage方法插入消息后,Handler的Looper会去取消息出来,然后调用Handler的handleMessage方法。所以handleMessage方法执行的线程就是Looper所在的线程,这样就从调用sendMessage方法的子线程切换到了调用handleMessage方法的Looper所在的线程了。

使用Handler的3种方式
public class HandlerActivity extends Activity {
    private Handler myHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myHandler = new Handler();

        new Thread(new Runnable() {
            @Override
            public void run() {
                myHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.d(Thread.currentThread().getName(),"receive message");
                    }
                });
            }
        }).start();
    }
}
注意点

今天你进步了嘛?欢迎关注我的微信公众号,和我一起每天进步一点点!


AntDream
上一篇下一篇

猜你喜欢

热点阅读