Android Handler 机制

来源:互联网 发布:美国历史gdp数据统计 编辑:程序博客网 时间:2024/06/06 00:40

在Android中消息机制是最常见的,那么说到消息机制就要说说Handler。
Handler机制中包含了四个主要部分:Handler、Message、MessageQuene、Looper
首先来说说Handler Handler可以理解为处理者就是对消息(message)进行对应的处理,同时它也是发送者,消息在发送的时候必须要通过Handler对象将消息发送出去。在这里简单的说了一下Handler的作用就是处理消息发送消息的东西。
接下来说说Message,Message即为消息在Android的Handler机制中就是通过Message来实现消息传递的,Message可以理解为就是一个载体。
MessageQuene消息队列用来存储消息的,通常一个进程/线程都会有一个MessageQuene。
Looper轮询器,它的主要功能就是将MessageQuene中的Message取出来交给对应的Handler进行处理一般来说一个进程/线程有一个Looper但是普遍的情况我们都是使用MainThread中的Looper。并且在同一个线程/进程中只能有一个Looper对象。
下面说一下整个机制的执行流程
首先在Android应用刚启动的时候系统就会为当前的应用创建一个Looper和一个MessageQuene,那么Looper和MessageQuene就不需要我们关心了我们只需要关心什么时候调用Handler对象将Message对象发送出去,其实这是很正常的但是我们只知道Handler对象发送完Message之后再接收这个Message对象进行处理是不够的,我们应该知道是怎么将这个Message交给对应的Handler的。下面直接上代码:

btnTest.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                new Thread(new Runnable() {                    @Override                    public void run() {                        Message msg = Message.obtain();//                        msg.what = 2;                        msg.what = 1;                        handlerOne.sendMessage(msg);//                        msg.setTarget(handlerTwo);//                        msg.getTarget().sendMessage(msg);                    }                }).start();                new Thread(new Runnable() {                    @Override                    public void run() {                        Message msg = Message.obtain();                        msg.what = 2;                        handlerTwo.sendMessageDelayed(msg, 2000);                    }                }).start();            }        });

当我们点击按钮之后会启动两个线程这个两个线程中产生了两个不同的消息并且由两个不同Handler对象进行处理现在就拿handlerOne来说当调用了sendMessage之后Handler这个类内部会将这个msg对象加入到对应的跟这个Handler绑定的消息队列中,那么这个消息队列是什么时候跟这个Handler进行绑定的呢,就是在这个Handler刚创建的时候

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;    }    public static @Nullable Looper myLooper() {        return sThreadLocal.get();    }从上面的代码我们可以看出在Handler创建的时候对应的Looper和MessageQuene都与当前的Handler进行了绑定,那么当我们调用Handler对象发送消息的时候就可以将消息发送到对应的消息队列中去了之后对应的Looper就会从对应的消息队列中取出消息交给对应的Handler让其处理消息,那么Looper与MessageQuene又是怎么绑定的呢Looper又是怎么取出消息的呢Looper与MessageQuene进行绑定的时候也是在Looper创建的时候,同时与Looper绑定的还有当前的Looper属于哪个线程的,关于Looper是怎么取出消息的相信大家应该可以想到就是做了一个死循环不停的访问消息队列中的内容代码如下:

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();    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);        }        final long traceTag = me.mTraceTag;        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));        }        try {            msg.target.dispatchMessage(msg);        } finally {            if (traceTag != 0) {                Trace.traceEnd(traceTag);            }        }        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();    }}

“`
当取出了消息之后会根据msg对象的target将这个msg对象交给对应的Handler进行处理
那么msg对象中的target是什么时候与msg绑定的呢,实际上在handler发送消息的时候target就与msg进行了绑定。在looper取出消息调用msg.target.dispatchMessage(msg);之后对应的handler对象就会调用handleMessage方法处理消息,那么说到这里Android Handler机制基本上大致理清楚了。

原创粉丝点击