所要用到的android源码路径:

ActivityThread源码路径:android-4.0.3_r1\frameworks\base\core\java\android\app\ActivityThread

Activity源码路径:android-4.0.3_r1\frameworks\base\core\java\android\app\Activity

Handler源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\Handler

Looper源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\Looper

Message源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\Message

MessageQueue源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\MessageQueue


我们从使用handler发送一条message到接收进行处理的这个过程来理解Handler,Looper,MessageQueue的实现,在Activity主线程中,会默认

创建一个Looper对象,在这个Looper类中会创建一个MessageQueue的消息队列,然后主线程会调用Looper的的loop()方法循环遍历这个消息队

列,如果有消息则会通过Handler对象将消息传递到handlerMessage方法中进行处理,如果Hanlder对象为空也就是没有创建Hanlder对象则会将

这条消息丢掉。那么消息的发送是怎样的呢?我们创建一个Handler对象,使用这个对象发送Message,其实是使用Looper对象传递进来的

MessageQueue,通过这个消息队列的引用将Message放进消息队列中,由于Looper会遍历这个队列,所以Handler对象发送msg,将其放进消

息队列,Looper遍历消息队列将消息取出,然后传递给Hanlder进行处理,这样一个消息的发送与接收就完成了。

首先我们根据Handler的构造函数来了解Handler的几种使用方法,从API中我们知道Handler有四个构造函数,分别是:

Handler()Handler(callback)Handler(looper)Handler(looper, callback)

一、不带参数的Handler()构造函数,其使用的是主线程默认的Looper对象以及MessageQueue

Handler handler2 = new Handler(){public void handleMessage(Message msg) {};};handler2.sendEmptyMessage(30);
直接在Activity中new一个Handler对象,并且重载handlerMessage方法就能够实现Message的发送与接收。

二、Handler(callback)构造函数,带了一个Hanlder类中的一个Callable接口对象作为参数,看源码就能够很清楚知道,他的作用其实是将handlerMessage

方法给独立出去,也就是在Activity中如果handlerMessage中的代码量太多,使用这个构造函数去创建对象,就能够将handlerMessage方法不放在

Activity中。

public class MyHandler implements Handler.Callback{@Overridepublic boolean handleMessage(Message arg0) {return false;}}
先实现Hanlder.Callback接口,丛杂handlerMessage方法,在这里进行消息的处理

MyHandler callback = new MyHandler();Handler handler3 = new Handler(callback);handler3.sendEmptyMessage(20);
在Activity中创建Handler对象,将Callback对象作为参数传递进去,然后使用handler发送Message,就能够在MyHandler中接收消息进行处理。

三、Handler(looper)构造函数,带了一个自定义的Looper对象作为参数,所以我们只要自定义一个Looper,然后将该Looper对象传递进去就能够正常

的进行消息发送与接收。但是我们不必要真的去自定义一个Looper类,我们只需要继承android已经实现好的HandlerThread线程,就能够自定义一个

Looper类

public class MyThread extends HandlerThread{//HandlerThread类是android中已经继承Thread的类,他已经帮你实现了Looper对象的创建//所以如果我们在实现Handler时,需要自定义Looper对象,则直接继承此类就行。public MyThread(String name) {super(name);}@Overrideprotected void onLooperPrepared() {//这个方法是在Looper.loop()被调用前在线程HandlerThread的run方法中被调用//所以如果要在这之前做什么操作,就需要重载这个方法Log.i("MyThread", "onLooperPrepared");super.onLooperPrepared();}}

MyThread thread = new MyThread("thread");thread.start();Looper looper = thread.getLooper();Handler handler1 = new Handler(looper){public void handleMessage(Message msg) {}};handler1.sendEmptyMessage(10);

这样我们就能够使用自定义的Looper进行消息的发送与接收,而不必使用Activity帮我们已经创建好的默认的Looper对象。


四、Handler(looper, callback)构造函数,知道了前面三种构造函数之后,这种就能够很容易理解了:使用自定义Looper,将handlerMessage方法

从创建Handler对象的类中独立出去。

Handler的详细使用方法就介绍完了,接下来我们就来分析相关类的源码,来彻底了解其运作过程。

首先我们来看看Looper的实现过程,我们知道在创建一个Activity时,其主UI主线程ActivityThread中会默认创建一个Looper对象,那么这个对象是在

什么地方创建的呢?

    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);        Process.setArgV0("<pre-initialized>");        Looper.prepareMainLooper();        if (sMainThreadHandler == null) {            sMainThreadHandler = new Handler();        }        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }

step1:从上面ActivityThread源码中我们可以看见,这个main方法是主线程的启动的地方,首先他调用了Looper的静态prepareMainLooper()方法:

    public static void prepareMainLooper() {        prepare();        setMainLooper(myLooper());        myLooper().mQueue.mQuitAllowed = false;    }

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

    private synchronized static void setMainLooper(Looper looper) {        mMainLooper = looper;    }
    public static Looper myLooper() {        return sThreadLocal.get();    }
    private Looper() {        mQueue = new MessageQueue();        mRun = true;        mThread = Thread.currentThread();    }
在上面源码中我们可以看出,prepareMainLooper方法中调用prepare()方法创建了一个Looper对象,并将这个Looper对象放进了ThreadLocal中,将

Looper对象放进ThreadLocal中的作用是,ThreadLocal会维护Looper对象中变量的副本。具体可以参考ThreadLocal的使用方法。然后调用myLooper

方法从ThreadLocal中获取Looper对象,并将其赋值给主线程Looper对象的引用。在Looper构造函数中我们可以看见,他创建了一个MessageQueue

对象,同时获取了Looper对象所在当前线程的引用。这样一个Looper对象便创建成功。

step2:然后判断主线程的Handler是否为空,如果为空则默认创建一个Handler对象,但是在源码中这个默认的Handler时候从来就没使用过,
估计是既然已经默认创建了Looper,那么也默认创建一个Handler对象。
step3: 创建主线程ActivityThread对象,然后调用loop()方法

    public static void loop() {        Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        MessageQueue queue = me.mQueue;        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();                while (true) {            Message msg = queue.next(); // might block            if (msg != null) {                if (msg.target == null) {                    // No target is a magic identifier for the quit message.                    return;                }                long wallStart = 0;                long threadStart = 0;                // This must be in a local variable, in case a UI event sets the logger                Printer logging = me.mLogging;                if (logging != null) {                    logging.println(">>>>> Dispatching to " + msg.target + " " +                            msg.callback + ": " + msg.what);                    wallStart = SystemClock.currentTimeMicro();                    threadStart = SystemClock.currentThreadTimeMicro();                }                msg.target.dispatchMessage(msg);                if (logging != null) {                    long wallTime = SystemClock.currentTimeMicro() - wallStart;                    long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);                    if (logging instanceof Profiler) {                        ((Profiler) logging).profile(msg, wallStart, wallTime,                                threadStart, threadTime);                    }                }                // 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.recycle();            }        }    }

在loop方法中,首先获取之前创建的Looper对象,MessageQueue对象,清除所有之前的访问标志,然后下面就是一个while死循环,在这个while循环

中,通过Message msg = queue.next()不停的从消息队列中获取Message,然后判断获取的Message是否为空,不为空,则判断这个Message的target

是否为空,通过了解Message源码我们知道,这个target其实就是一个Handler对象,也就是如果在没有创建Handler对象,则这个Message不进行处理

直接返回,继续去下一个Message。如果已经创建了Handler对象,则通过msg.target.dispatchMessage(msg)将从消息队列中获取的Message传递

到Handler中。

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

在dispatchMessage中将消息传递到handlerMessage(msg)中,这样handler便接收到了一个Message。

通过上面三步,当一个Activity启动时,其主线程ActivityThread创建成功后,会默认创建一个Looper对象,一个消息队列。同时会循环遍历这个消息

队列,而不会管Handler对象有没有创建。

下面我们来看Handler是怎样发送一个消息进消息队列的,首先了解Hanlder的初始化过程:

    public Handler() {        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 = null;    }

从Handler的构造函数中我们可以看到,通过Looper.myLooper()获取Looper对象的引用,通过mLooper.mQueue获取消息队列的引用。

接下来我们看发送消息的方法:

    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)    {        boolean sent = false;        MessageQueue queue = mQueue;        if (queue != null) {            msg.target = this;            sent = queue.enqueueMessage(msg, uptimeMillis);        }        else {            RuntimeException e = new RuntimeException(                this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);        }        return sent;    }
从上面源码可以看到,调用sendMessage其实是调用sendMessageDelayed方法,在sendMessageDelayed方法中调用了sendMessageAtTime方法

sendMessageAtTime才是最终发送Message的地方,在sendMessageAtTime中我们可以看到,首先判断消息队列的引用是否为空,不为空则调用

enqueueMessage方法将Message放进消息队列中。在这个方法中我们还可以看到通过msg.target = this,Message获取到了当前Handler对象的引用

final boolean enqueueMessage(Message msg, long when) {        if (msg.isInUse()) {            throw new AndroidRuntimeException(msg                    + " This message is already in use.");        }        if (msg.target == null && !mQuitAllowed) {            throw new RuntimeException("Main thread not allowed to quit");        }        final boolean needWake;        synchronized (this) {            if (mQuiting) {                RuntimeException e = new RuntimeException(                    msg.target + " sending message to a Handler on a dead thread");                Log.w("MessageQueue", e.getMessage(), e);                return false;            } else if (msg.target == null) {                mQuiting = true;            }            msg.when = when;            //Log.d("MessageQueue", "Enqueing: " + msg);            Message p = mMessages;            if (p == null || when == 0 || when < p.when) {                msg.next = p;                mMessages = msg;                needWake = mBlocked; // new head, might need to wake up            } else {                Message prev = null;                while (p != null && p.when <= when) {                    prev = p;                    p = p.next;                }                msg.next = prev.next;                prev.next = msg;                needWake = false; // still waiting on head, no need to wake up            }        }        if (needWake) {            nativeWake(mPtr);        }        return true;    }

要理解enqueueMessage源码,就必须结合Looper获取消息的方法来理解:

    final Message next() {        int pendingIdleHandlerCount = -1; // -1 only during first iteration        int nextPollTimeoutMillis = 0;        for (;;) {            if (nextPollTimeoutMillis != 0) {                Binder.flushPendingCommands();            }            nativePollOnce(mPtr, nextPollTimeoutMillis);            synchronized (this) {                // Try to retrieve the next message.  Return if found.                final long now = SystemClock.uptimeMillis();                final Message msg = mMessages;                if (msg != null) {                    final long when = msg.when;                    if (now >= when) {                        mBlocked = false;                        mMessages = msg.next;                        msg.next = null;                        if (false) Log.v("MessageQueue", "Returning message: " + msg);                        msg.markInUse();                        return msg;                    } else {                        nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);                    }                } else {                    nextPollTimeoutMillis = -1;                }                // If first time, then get the number of idlers to run.                if (pendingIdleHandlerCount < 0) {                    pendingIdleHandlerCount = mIdleHandlers.size();                }                if (pendingIdleHandlerCount == 0) {                    // No idle handlers to run.  Loop and wait some more.                    mBlocked = true;                    continue;                }                if (mPendingIdleHandlers == null) {                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];                }                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);            }            // Run the idle handlers.            // We only ever reach this code block during the first iteration.            for (int i = 0; i < pendingIdleHandlerCount; i++) {                final IdleHandler idler = mPendingIdleHandlers[i];                mPendingIdleHandlers[i] = null; // release the reference to the handler                boolean keep = false;                try {                    keep = idler.queueIdle();                } catch (Throwable t) {                    Log.wtf("MessageQueue", "IdleHandler threw exception", t);                }                if (!keep) {                    synchronized (this) {                        mIdleHandlers.remove(idler);                    }                }            }            // Reset the idle handler count to 0 so we do not run them again.            pendingIdleHandlerCount = 0;            // While calling an idle handler, a new message could have been delivered            // so go back and look again for a pending message without waiting.            nextPollTimeoutMillis = 0;        }    }

在enqueueMessage中我们看到,首先判断Message的target即所属的Handler对象是否为空,为空则抛出RuntimeException异常,然后定义了一个

final boolean needWake变量,注意他没有进行初始化,而且为final类型,表明一旦其被初始化后就无法再次进行更改了,然后就是一个同步块,在

这个同步块中,首先获取一个全局Message对象mMessages的引用,如果这个Message不是延迟性或者空的消息,那么将这个msg赋值给这个全局

的Message对象mMessages,并且将mBlocked赋值给needWake,在MessageQueue源码中,可以看见mBlocked定义时是没有初始化的,那么

在哪里初始化呢?这就要看next()方法了。

我们知道在主UI线程创建时,Looper对象就会创建,就会调用loop()方法,就会调用next()方法循环遍历消息队列,由于一开始消息队列为空,所以

msg一定为空,执行的只是下面这段代码:

                if (pendingIdleHandlerCount < 0) {                    pendingIdleHandlerCount = mIdleHandlers.size();                }                if (pendingIdleHandlerCount == 0) {                    // No idle handlers to run.  Loop and wait some more.                    mBlocked = true;                    continue;                }
从这里就能够看见,mBlocked一开始是初始化为true的,所以在同步方法块执行完毕后,会调用nativeWake方法。在next()方法中可以看见,其消息

操作的逻辑也是一个同步方法块,而且注意到了没有?他操作的Message不是从什么队列中获取的,其实操作的就是那个全局的Message对象

mMessages,并且从MessageQueue的其他removeMessages等方法可以看到,所有操作全局对象mMessages都是在方法同步块中的,所以我们

就应该能够明白了MessageQueue不是用什么消息队列来保存Message的,而只是使用一个全局的mMessages来保存的,每次Looper循环遍历的

都是mMessages对象,获取到之后然后将这个对象置为空,如果next()在调用,则其他方法调用处于阻塞状态,如果enqueueMessage处于调用中

则其他调用的方法处于阻塞中,所以当有多个线程同时调用同一个Handler对象发送Message时,其中只有一个线程调用的方法是处于运行状态的,

其他线程的调用是处于阻塞状态的,为什么android会这样进行处理呢?我觉得这么处理的原因是以时间换取空间,Handler发送消息的逻辑是相对

简单的,没有什么业务逻辑,也就是所需获取执行的时间是非常短的,而且不会出现很多线程同时使用同一个Handler来发送Message。

所以到这里我们就明白了MessageQueue的实现机制了:

1、MessageQueue不是什么消息队列,没有使用到队列,其使用的是一个全局对象来进行消息接收与发送

2、MessageQueue中所有的消息操作方法都是同步块的,当有一个方法被执行时,其他方法是处于阻塞状态的。

3、如果我们同时开启非常多的线程使用同一Handler发送消息或者移除消息,那么sendMessage(msg)不会立即返回结果的。

4、在多个线程中不要大量使用Handler来操作Message。他只适合于少量线程中进行使用。

这样Handler的消息发送以及Looper的消息获取就都剖析完了。Handler,Looper,MessageQueue的实现也就完全讲完了。

总结:

在我们创建一个Activity时,会自动创建一个Looper对象,并且在Looper的构造方法中会创建一个MessageQueue的对象,当Activity的主线程启动

时,会调用Looper的loop()方法循环检查MessageQueue中的全局对象mMessages是否为空,如果不为空则会调用相应Handler的

dispatchMessage方法,将这个消息传递到Handler中的handleMessage方法中进行处理。当我们创建一个Handler对象,使用这个Handler对象

发送消息时,最终调用的是MessageQueue中的enqueueMessage,消息的所有的操作,如:发送,移除,遍历都是在MessageQueue中进行

操作的,这也对应了面向对象的及迪米特法则,也就是所有该类的职责应该就在该类中完成,尽量少于外界进行联系。消息的处理是单个操作的

当一个消息在发送时,其他消息的发送是处于阻塞状态,由于消息操作的业务逻辑简单,所以不必过于关注消息操作的延时性,但是不应在大量

线程中使用Handler进行消息传递。










更多相关文章

  1. Android 获取控件宽高的3种方法
  2. Android中创建与几种解析xml的方法!
  3. Android当方法总数超过64K时(Android Studio)
  4. android ViewPager 使用方法
  5. Android 方法数超过64k限制的解决办法
  6. android的Services生命周期和使用方法
  7. Android onClick事件三种实现方法
  8. android学习——android 常见的错误 和 解决方法
  9. Android详细的对话框AlertDialog.Builder使用方法

随机推荐

  1. 对比onSaveInstanceState和onRestoreInst
  2. Android中的通知Notification
  3. Android(安卓)效果
  4. android下无预览摄像
  5. android自动更新软件版本
  6. Android(安卓)实现apk文件下载并自动安装
  7. Android(安卓)自定义相机
  8. android使用Dialog跳转到Activity
  9. android gradle多渠道打包配置
  10. Android(安卓)实现断点续传