Handler机制解析

来源:互联网 发布:打车软件补贴方案 编辑:程序博客网 时间:2024/05/16 06:06

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);        }    };
原创粉丝点击