Handler是Android中的核心类,它的作用主要是进行更新UI的操作,使用非常的简单,因为它的内部已经被Google工程师封装好了,我们只需要简单的调用即可。但是作为一个有梦想的程序猿,不应该止于使用的层面,要想有所提高,对其内部的原理,我们有必要熟知一二。闲言少叙,在下这就开始上菜。
一,获取消息对象的方式
1、最简单粗暴的方式:
Message message = new Message();
2、通过消息池去取消息:
Message.obtain()方法如下:
从消息池中取消息,如果没有消息就new一个,避免创建多个对象/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { 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(); }
3、通过handler对象获取消息:handler.obtainMessage();
源码如下:/** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ public final Message obtainMessage() { return Message.obtain(this); }
再次点击跳转
通过源码可以发现,handler.obtainMessage()还是调用的Message.obtain();/** * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. * @param h Handler to assign to the returned Message object's <em>target</em> member. * @return A Message object from the global pool. */ public static Message obtain(Handler h) { Message m = obtain(); m.target = h; return m; }
好了创建消息对象的过程到此结束。
二、创建handler对象
1、在使用handler的时候上会在主线程上new handler并且重写handleMessage方法击new handler的构造方法看他干了什么Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } };
继续点击查看/** * Default constructor associates this handler with the {@link Looper} for the * current thread. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. */ public Handler() { this(null, false); }
看红色标记的,Loop是什么鬼?不知道我们就点击看下他是什么呗public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } 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; }
通过 sThreadLocal.get()获取一个Loop对象/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
ThreadLocal是一个单个线程数据传递的一个类,他能保证在哪个线程存,只能在哪个线程取。关于他的实现网上有很多优秀的文章,这里不做介绍。问题来了,那这个loop对象又是什么时候存放的呢?我们知道一个程序的入口是ActivityThread这个类,他只有一个main方法2、loop对象的创建public static void main(String[] args) { SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Environment.initForCurrentUser(); // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); Security.addProvider(new AndroidKeyStoreProvider()); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper();//在这里放置一个loop对象 ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } AsyncTask.init(); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } }
源码可以看到Looper.prepareMainLooper();点击查看
继续查看/** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
此时可以看出,为ThreadLocal设置一个Loop对象,这就是为什么可以通过ThreadLocal.get()获取loop对象了。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)); }
我们再看看loop的构造方法里面干了什么创建loop的同时会给我们创建MessageQueue对象,这个对象在后面会讲。暂且记住有这个东东。private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
这样loop对象就已经有了,在ActivityThread的main方法里,会继续调用Loop.loop()方法。暂且在这里停留片刻,我们先回到handler的分析。
3、再次回到handler刚才通过mLooper = Looper.myLooper();获取loop对象,再将loop对象中的 MessageQueue对象赋值给handler中的成员变量此时handler对象已经创建完毕了
4、handler发送消息通过最简单的方式发送一个消息 handler.sendMessage(msg)继续查看public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
nextpublic final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
这里会把之前消息对象mQuene传递到 enqueueMessage方法中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); }
这里会把this也就是handler对象赋值给msg.targetprivate boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
并且会调用 MessageQueue 的queue.enqueueMessage(msg, uptimeMillis)
boolean enqueueMessage(Message msg, long when) { ----------省略--------------- 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. msg.next = p; mMessages = msg; needWake = mBlocked; } else { // Inserted within the middle of the queue. Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. 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; }
这里会对消息通过when时间进行排序,时间小的先发送,时间长的后发送(这里还没有发送,只是排好先后顺序,等比人来取),这里发送消息的过程已经结束。
4、取消息