Handler机制解析

Posted nangongyibin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Handler机制解析相关的知识,希望对你有一定的参考价值。

Hanlder机制用于线程间通信,通常用于子线程给主线程发送消息更新UI

Handler 
Message的主要处理者,用于发送消息,接收处理消息 
Message 
消息,线程间通信的数据单元 
MessageQueue 
消息队列,用于存放消息,取出消息 
Looper 
循环器,Message和Handler的桥梁,循环取出MessageQueue的消息发送Handler

需要注意几点:

在创建Handler之前,需要调用Looper.prepare()方法,之所以平常使用未调用过,是因为android在程序启动时帮我们创建好了,具体代码在activityThread中的main()方法中,

public static void main(String[] args) {

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        SamplingProfilerIntegration.start();

        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        EventLogger.setReporter(new EventLoggingReporter());

        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

 

        Looper.prepareMainLooper();//在此调用的Looper.prepare()

 

        ActivityThread thread = new ActivityThread();

        thread.attach(false);

        if (sMainThreadHandler == null) {

            sMainThreadHandler = thread.getHandler();

        }

        if (false) {

            Looper.myLooper().setMessageLogging(new

                    LogPrinter(Log.DEBUG, "ActivityThread"));

        }   

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

 

        Looper.loop();

 

        throw new RuntimeException("Main thread loop unexpectedly exited");

    }

 

因此我们在子线程使用Handler的时候,需要调用Looper.prepare()方法

class LooperThread extends Thread { 

      public Handler mHandler; 

 

      public void run() { 

          Looper.prepare(); 

 

          mHandler = new Handler() { 

              public void handleMessage(Message msg) { 

                  // process incoming messages here 

              } 

          }; 

 

          Looper.loop(); 

      } 

  } 

 

调用Looper.prepare()方法后只能确保在创建Handler的时候不报错,如果不调用Looper.loop()方法,则没有任何效果,同样,android在程序启动时,已经为我们做好了这一步

public static void main(String[] args) {

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        SamplingProfilerIntegration.start();

        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        EventLogger.setReporter(new EventLoggingReporter());    

        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

 

        Looper.prepareMainLooper();//在此调用的Looper.prepare()

 

        ActivityThread thread = new ActivityThread();

        thread.attach(false);

        if (sMainThreadHandler == null) {

            sMainThreadHandler = thread.getHandler();

        }

        if (false) {

            Looper.myLooper().setMessageLogging(new

                    LogPrinter(Log.DEBUG, "ActivityThread"));

        }

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

 

        Looper.loop();//在此调用的Looper.loop()

 

        throw new RuntimeException("Main thread loop unexpectedly exited");

    }

 

Handler的工作原理

当我们启动程序的时候,android自动在ActivityThread中帮我们创建了Looper.prepare()方法,创建了Looper对象. 
在调用Looper.prepare()方法时,会创建Looper对象,当前线程会将Looper的对象保存,并且在Looper构造方法中,创建MessageQueue对象,也就是说一个Looper一个MessageQueue

 

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));

    }

 private Looper(boolean quitAllowed) {

        mQueue = new MessageQueue(quitAllowed);

        mThread = Thread.currentThread();

    }

 

Handler调用postMessage之类的方法,最后都会调用sendMessageAtTime()方法,其中有queue.equeueMessage(msg)方法,实际就是消息入列逻辑

public boolean sendMessageAtTime(Message msg, long uptimeMillis){ 

    boolean sent = false; 

    MessageQueue queue = mQueue; 

    if (queue != null) { 

        msg.target = this; 

        //该方法为将消息添加到MessageQueue

        sent = queue.enqueueMessage(msg, uptimeMillis); 

    } 

    else { 

        RuntimeException e = new RuntimeException( 

            this + " sendMessageAtTime() called with no mQueue"); 

        Log.w("Looper", e.getMessage(), e); 

    } 

    return sent; 

} 

final boolean enqueueMessage(Message msg, long when) { 

    if (msg.when != 0) { 

        throw new AndroidRuntimeException(msg + " This message is already in use."); 

    } 

    if (msg.target == null && !mQuitAllowed) { 

        throw new RuntimeException("Main thread not allowed to quit"); 

    } 

    synchronized (this) {    10    9

        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; 

        } 

        //将消息的时间传进来赋给Message

        msg.when = when; 

        Message p = mMessages;        0

        if (p == null || when == 0 || when < p.when) { 

            msg.next = p; 1

                //将要取出的消息

            mMessages = msg;    0

            this.notify(); 

        } else { 

            Message prev = null; 

            while (p != null && p.when <= when) { 

                prev = p; 

                p = p.next; 

            } 

            msg.next = prev.next; 

            prev.next = msg; 

            this.notify(); 

        } 

    } 

    return true; 

} 

 

由上面我们可以得知,其实MessageQueue并没有用集合将消息存储起来,而是mMessages对象表示当前待处理的消息,所谓的加入队列其实就是将所有的消息按时间进行排序,具体的操作就是根据Message的时间,去调用msg.next。 
从消息取出消息队列是通过Looper.loop(),实际上是一个死循环,不断调用MessageQueue.next方法,他其中的操作就是判断当前是否有需要处理的消息,如果有,则取出来,将下个消息成为mMessages,否则就进入阻塞状态,一直等待新消息的加入。

public static final void loop() { 

    Looper me = myLooper(); 

    MessageQueue queue = me.mQueue; 

    while (true) { 

        Message msg = queue.next(); // might block 

        if (msg != null) { 

            if (msg.target == null) { 

                return; 

            } 

            if (me.mLogging!= null) me.mLogging.println( 

                    ">>>>> Dispatching to " + msg.target + " " 

                    + msg.callback + ": " + msg.what 

                    ); 

            msg.target.dispatchMessage(msg); 

            if (me.mLogging!= null) me.mLogging.println( 

                    "<<<<< Finished to    " + msg.target + " " 

                    + msg.callback); 

            msg.recycle(); 

        } 

    } 

} 

 

在Looper.loop()方法中找到将要处理的消息后,会调用msg.target.disPatcheMessage()方法,msg.target就是Handler.也就是调用了Handler.disPatchMessage()方法,在这个方法中,会判断mCallBack是否为空,如果不为空调用callback,如果为空,则调用了handlerMessage()方法,至此整个消息处理完成

public void dispatchMessage(Message msg) { 

    if (msg.callback != null) { 

        handleCallback(msg); 

    } else { 

        if (mCallback != null) { 

            if (mCallback.handleMessage(msg)) { 

                return; 

            } 

        } 

        handleMessage(msg); 

    } 

} 

 

对于上条的mCallBack,是因为在创建Handler对象的时候可以传入一个CallBack对象,如果return true,下面的handlermessage就不会收到消息,反正则能收到消息

   

private Handler mHandler = new Handler(new Handler.Callback() {

        @Override

        public boolean handleMessage(Message msg) {

            //返回为true则下面的handlerMessage不能收到消息

            //返回false则下面的hanlderMessage能够收到消息

            return false;

        }

    }){

        @Override

        public void handleMessage(Message msg) {

            super.handleMessage(msg);

        }

    };

 

以上是关于Handler机制解析的主要内容,如果未能解决你的问题,请参考以下文章

Android Handler机制原理解析

Handler机制解析

Android Handler机制 源码解析

[Android进阶Handler机制原理解析

Android消息机制Handler解析(源码+Demo)

Android源代码解析之--&gt;异步任务AsyncTask