使用
class MyRunnable implements Runnable {
private Handler handler = null;
Handler getHandler() {
return handler;
}
@Override
public void run() {
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
Looper.loop();
}
}
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
Handler handler = runnable.getHandler();
if (handler != null) {
handler.post(new Runnable {
@Override
public void run() {
//抛到线程中处理任务
}
});
}
//发送消息到线程中处理
handler.sendMessage();
Loop.prepare
首先在使用 handler 之前我们都需要这样初始化, 在Android UI主线程中是隐式处理的。
//线程的本地变量,这个是个好东西,只能获取到当前线程保存的变量
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
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的代码
sThreadLocal.set(new Looper(quitAllowed));
}
final class Looper {
@UnsupportedAppUsage
final MessageQueue mQueue;
final Thread mThread;
//实质上是创建一个消息队列,保存一下当前线程的引用
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
Looper.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;
//我也没怎么看懂,有点像获取当前进程的身份ID的意思
// 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 {
//target指的就是handler,这个就是分发消息的东西了, 核心应该是这个部分
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();
}
}
public final class MessageQueue {
Message next() {
...
...
//暴力的循环获取
for (;;) {
...
...
//能看到这个是一个同步的操作
synchronized (this) {
}
...
...
}
}
//消息入队的操作
boolean enqueueMessage(Message msg, long when) {
...
...
//同步入队
synchronized (this) {
...
...
//有意思的是我们可以看到队列的结构是单向链式
}
...
...
}
}
Handler
到这里就是使用部分了
public class Handler {
//post 和 postDelay方法使用的都是直接调用这个方法,所以重点关注一下
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);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//这边我们可以看到target实际上指的就是handler
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//入队了
return queue.enqueueMessage(msg, uptimeMillis);
}
}
总结
简单的过了一下源码,能看到其实很多参数没有提及,这个需要实际应用的时候才知道,大致就是使用线程标记一个循环,并且,启动循环, Handler实际上是和循环挂钩的, 通过向循环抛入消息的方式,在线程之间传递消息。