android handler线程原理详详解

这篇也超级有用,保存下来以后忘了可以再看。

 

在开发Android应用程序中,有时候我们需要在应用程序中创建一些常驻的子线程来不定期地执行一些不需要与应用程序界面交互的计算型的任务。如果这些子线程具有消息循环,那么它们就能够常驻在应用程序中不定期的执行一些计算型任务了:当我们需要用这些子线程来执行任务时,就往这个子线程的消息队列中发送一个消息。然后就可以在子线程的消息循环中执行我们的计算型任务了、

    在Android,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper,这个是android的新概念。我们的主线程(UI线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handler,我们有消息循环,就要往消息循环里面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,消息的的处理,把这些都封装在Handler里面,注意Handler只是针对那些有Looper的线程,不管是UI线程还是子线程,只要你有Looper,我就可以往你的消息队列里面添加东西,并做相应的处理。
 
    如果在子线程里面新建handler,就会出现错误。原因就是一个线程对应一个或者零个Looper和MessageQue。handler是一种消息机制,而子线程的启用默认是没有Looper对象的(主线程有),所以在子线程使用Handler对象的时候,要先使用Looper.prepare(),启用一个Looper ,然后新建Handler对象,再使用Looper.loop()。
至此子线程就有了自己的Looper,可以接受和处理消息。
 

android.os.Looper:

Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。

注:写在Looper.loop()之后的代码不会被立即执行,当调用后mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。

 

以下是Android API中的一个典型的Looper thread实现:
//Handler不带参数的默认构造函数:new Handler(),实际上是通过Looper.myLooper()来获取当前线程中的消息循环,
//而默认情况下,线程是没有消息循环的,所以要调用 Looper.prepare()来给线程创建消息循环,然后再通过,Looper.loop()来使消息循环起作用。
  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();
      }
  }

另,Activity的MainUI线程默认是有消息队列的。所以在Activity中新建Handler时,不需要先调用Looper.prepare()。

android.os.Handler:

Handler用于跟线程绑定,来向线程的消息循环里面发送消息、接受消息并处理消息。

以下是不带参数的Handler构造器:

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

//如果当前线程里面没有消息循环的时候,系统抛出异常。即在一个线程里如果想用Handler来处理消息,是需要调用Looer.prepare()来创建消息循环的,而MainUI线程不需要。

            throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }

通过以下函数来向线程发送消息或Runnable:
1、post(Runnable)postAtTime(Runnable, long)postDelayed(Runnable, long);
  当线程接收到Runnable对象后即立即或一定延迟调用。
2、sendEmptyMessage(int)sendMessage(Message)sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long)。
  当线程接受到这些消息后,根据你的Handler重构的handleMessage(Message)根据接收到的消息来进行处理。
 
另,一个Activity主线程中可以有多个Handler对象,但MessageQueueLooper是只有一个,对应的Looper也是只有一个。

.MessageQueue 
顾名思义就是消息队列,干什么用的 当然是存放消息用的
 
Looper类的静态成员函数prepareMainLooper是专门应用程序的主线程调用的,为了让其它地方能够方便地通过Looper类的getMainLooper函数来获得应用程序主线程中的消息循环对象。
 
原文链接:http://blog.csdn.net/chengyingzhilian/article/details/7646895

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。