Looper用于在android线程中进行消息处理,默认情况下,一个线程并不和任何Looper绑定。当我们调用Looper.prepare()时,如果当前线程还没有和任何Looper绑定,那么将创建一个Looper让它和当前线程绑定。当我们调用Looper.loop()时,它将对当前线程所对应的Looper的消息进行处理,从消息队列里取消息,处理消息,一直循环直到对该Looper调用 quit() 函数。


注意:Looper.loop()中是个while循环,只有对它所在线程的Looper调用了quit()函数,Looper.loop()函数才能完成,其后的代码才能得以运行。一个线程对应一个Looper,一个Looper对应一个消息队列MessageQueue。


   对于Handler,其实只是把消息发送到其对应的Looper的消息队列MessageQueue中,最后的处理还是在Looper.loop()的while循环中进行的。一个Looper可以用于构造多个Handler。因为Looper.loop()函数是个while循环,会让当前线程一直在那里处理进行循环,直到对该线程的Looper调用了quit()函数,所以 , 如果想对该Handler发送消息或添加Runnable以进行事务处理,要么在别的线程中进行,要么在该Handler在处理消息时或在Runnable()的run()函数中进行事务处理时进行。


注意1:Handler的构造函数Handler()和Handler(Handler.Callback callback),虽然没有Looper参数,但是它实际上是通过Looper.myLooper()来获取当前线程中的Looper的。


注意2:如果你使用的Looper来自于你自己创建的线程,那么在不使用其对应的Handler时候,一定要通过 handler.getLooper().quit()来使其线程退出。


以下是Android API中的一个典型的Looper thread实现


示例1

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的,所以要调用 Looper.prepare()来给线程创建消息循环,然后再通过,Looper.loop()来使消息循环起作用。

 
另外,Activity的MainUI线程已经新建并绑定了个Looper(在源码1的,Main函数中你可以看到)。所以在Activity中新建Handler时,不需要先调用Looper.prepare()。
 
关于
 Activity的MainUI线程的更多内容可以查看源码文件
 ActivityThread.java,
 它位于
 android\frameworks\base\core\java\android\app
 下
 
 
 源码1
 
public final class ActivityThread {
 
//省略
 
    
  final ApplicationThread mAppThread = new ApplicationThread();
 
 
    final Looper mLooper = Looper.myLooper();
 
 
    
  final H mH = new H();
 
 //省略 
private final class H extends Handler
   {
 
 

  //省略
 
 
 

  }
 
 
//省略
 
public static final void main(String[] args) {
 
 
        SamplingProfilerIntegration.start();
 
 

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

 
 
        if (Process.supportsProcesses()) {
 
 
            throw new RuntimeException("Main thread loop unexpectedly exited");
 
 
        }
 
 

 
 
        thread.detach();
 
 
        String name = (thread.mInitialApplication != null)
 
 
            ? thread.mInitialApplication.getPackageName()
 
 
            : "<unknown>";
 
 
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
 
 
    }
 
还Activity的生命周期函数(如onCreate(),onResume)本身也是通过 一个基于其MainUI线程的Looper(即ActivityThread的Main函数线程)的Handler(即ActivityThread的H mH这个Handler
 )来调用的.也就说这些函数都是在Looper.loop()中被执行的。当然如果我们创建了一个基于Activity本身的MainUI线程的Looper的Handler的话,该Handler的事务处理也是在Looper.loop()中进行的。我们从测试实例1也可以看到这一点。
 
 
 测试实例1
 :
 

  package com.teleca.robin;
 
 
 

  import android.app.Activity;
 
 
 

  import android.os.Bundle;
 
 
 

  import android.os.Handler;
 
 
 

  import android.util.Log;
 
 
 

  public class MainActivity extends Activity {
 
 
 

      /** Called when the activity is first created. */
 
 
 

      @Override
 
 
 

      public void onCreate(Bundle savedInstanceState) {
 
 
 

          super.onCreate(savedInstanceState);
 
 
 

          setContentView(R.layout.main);
 
 
 
       
   Log.i(tag,"-----------------------------------------------");
 
 
StackTraceElement st[]= Thread.currentThread().getStackTrace();
 
 
for(int i=0;i<st.length;i++)
 
 
Log.i(tag,i+":"+st[i]);
 
 

  Log.i(tag,"------------------------------------------------");
 
 
        handler=new Handler();
 
 
        handler.postDelayed(r, 100);
 
 
        handler2.postDelayed(r, 200);
 
 

      }
 
 
 

      final static String tag="robin";
 
 
 

      Handler handler;
 
 
 
   
   Handler handler2=new Handler();
 
 

      Runnable r=new Runnable(){
 
 
 
    
  
  public void run()
 
 
 {
 
 
 
 StackTraceElement st[]= Thread.currentThread().getStackTrace();
 
 
 for(int i=0;i<st.length;i++)
 
 
 Log.i(tag,i+":"+st[i]);
 
 
 Log.i(tag,"----------------------------------------------");
 
 
 
 }
 
 
 
 
 
 

      };
 
 
 

  }
 
 
:
 
07-20 22:10:18.799: INFO/robin(7844): -----------------------------------------------
 
 
07-20 22:10:18.819: INFO/robin(7844): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
 
 
07-20 22:10:18.819: INFO/robin(7844): 1:java.lang.Thread.getStackTrace(Thread.java:788)
 
 
07-20 22:10:18.819: INFO/robin(7844): 2:com.teleca.robin.MainActivity.onCreate(MainActivity.java:15)
 
 
07-20 22:10:18.819: INFO/robin(7844): 3:android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
 
 
07-20 22:10:18.819: INFO/robin(7844): 4:android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)
 
 
07-20 22:10:18.819: INFO/robin(7844): 5:android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2685)
 
 
07-20 22:10:18.819: INFO/robin(7844): 6:android.app.ActivityThread.access$2300(ActivityThread.java:126)
 
 
07-20 22:10:18.819: INFO/robin(7844): 7:android.app.ActivityThread$H.handleMessage(ActivityThread.java:2038)
 
 
07-20 22:10:18.819: INFO/robin(7844): 8:android.os.Handler.dispatchMessage(Handler.java:99)
 
 
07-20 22:10:18.819: INFO/robin(7844): 9:android.os.Looper.loop(Looper.java:123)
 
 
07-20 22:10:18.819: INFO/robin(7844): 10:android.app.ActivityThread.main(ActivityThread.java:4633)
 
 
07-20 22:10:18.819: INFO/robin(7844): 11:java.lang.reflect.Method.invokeNative(Native Method)
 
 
07-20 22:10:18.819: INFO/robin(7844): 12:java.lang.reflect.Method.invoke(Method.java:521)
 
 
07-20 22:10:18.819: INFO/robin(7844): 13:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
 
 
07-20 22:10:18.819: INFO/robin(7844): 14:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 
 
07-20 22:10:18.819: INFO/robin(7844): 15:dalvik.system.NativeStart.main(Native Method)
 
 
07-20 22:10:18.819: INFO/robin(7844): ------------------------------------------------
 
 
07-20 22:10:18.969: INFO/robin(7844): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
 
 
07-20 22:10:18.969: INFO/robin(7844): 1:java.lang.Thread.getStackTrace(Thread.java:788)
 
 
07-20 22:10:18.969: INFO/robin(7844): 2:com.teleca.robin.MainActivity$1.run(MainActivity.java:29)
 
 
07-20 22:10:18.969: INFO/robin(7844): 3:android.os.Handler.handleCallback(Handler.java:587)
 
 
07-20 22:10:18.969: INFO/robin(7844): 4:android.os.Handler.dispatchMessage(Handler.java:92)
 
 
07-20 22:10:18.969: INFO/robin(7844): 5:android.os.Looper.loop(Looper.java:123)
 
 
07-20 22:10:18.969: INFO/robin(7844): 6:android.app.ActivityThread.main(ActivityThread.java:4633)
 
 
07-20 22:10:18.969: INFO/robin(7844): 7:java.lang.reflect.Method.invokeNative(Native Method)
 
 
07-20 22:10:18.969: INFO/robin(7844): 8:java.lang.reflect.Method.invoke(Method.java:521)
 
 
07-20 22:10:18.969: INFO/robin(7844): 9:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
 
 
07-20 22:10:18.969: INFO/robin(7844): 10:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 
 
07-20 22:10:18.969: INFO/robin(7844): 11:dalvik.system.NativeStart.main(Native Method)
 
 
07-20 22:10:18.969: INFO/robin(7844): ----------------------------------------------
 
 
07-20 22:10:19.019: INFO/robin(7844): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
 
 
07-20 22:10:19.019: INFO/robin(7844): 1:java.lang.Thread.getStackTrace(Thread.java:788)
 
 
07-20 22:10:19.019: INFO/robin(7844): 2:com.teleca.robin.MainActivity$1.run(MainActivity.java:29)
 
 
07-20 22:10:19.019: INFO/robin(7844): 3:android.os.Handler.handleCallback(Handler.java:587)
 
 
07-20 22:10:19.019: INFO/robin(7844): 4:android.os.Handler.dispatchMessage(Handler.java:92)
 
 
07-20 22:10:19.019: INFO/robin(7844): 5:android.os.Looper.loop(Looper.java:123)
 
 
07-20 22:10:19.019: INFO/robin(7844): 6:android.app.ActivityThread.main(ActivityThread.java:4633)
 
 
07-20 22:10:19.019: INFO/robin(7844): 7:java.lang.reflect.Method.invokeNative(Native Method)
 
 
07-20 22:10:19.019: INFO/robin(7844): 8:java.lang.reflect.Method.invoke(Method.java:521)
 
 
07-20 22:10:19.019: INFO/robin(7844): 9:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
 
 
07-20 22:10:19.019: INFO/robin(7844): 10:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 
 
07-20 22:10:19.019: INFO/robin(7844): 11:dalvik.system.NativeStart.main(Native Method)
 
 
07-20 22:10:19.019: INFO/robin(7844): ----------------------------------------------
 
另外同过查看ActivityThread.java源码,你可以看到系统还会通过ApplicationThread mAppThread向该Handler发送消息,以便进行事务处理。
 
测试实例2 
MyService.java
 

  package com.lenovo.robin.test;
 
 
 

  
 
 

  import android.app.Service;
 
 
 

  import android.content.Intent;
 
 
 

  import android.os.IBinder;
 
 
 

  import android.util.Log;
 
 
 

  
 
 

  public class MyService extends Service {
 
 
 

  
 
 
String tag="robin";
 
 
 

      @Override
 
 
 

      public void onCreate() {
 
 
 

          Log.i(tag,"MyService is oncreate");
 
 
 

      }
 
 
 

  
 
 

      @Override
 
 
 

      public int onStartCommand(Intent intent, int flags, int startId) {
 
 
 
 StackTraceElement st[]= Thread.currentThread().getStackTrace();
 
 
 
 for(int i=0;i<st.length;i++)
 
 
 
 Log.i(tag,i+":"+st[i]);
 
 
 

          return START_STICKY;
 
 
 

      }
 
 
 

      @Override
 
 
 

      public void onDestroy() {
 
 
 

          Log.i(tag,"OnDestory");
 
 
 

      }
 
 
 

      @Override
 
 
 

      public IBinder onBind(Intent arg0) {
 
 
 

          return null;
 
 
 

      }
 
 
 

  
 
 

  }
 
 

  测试结果

 
08-12 22:11:30.950: I/robin(26133): MyService is oncreate
 
 
08-12 22:11:30.960: I/robin(26133): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
 
 
08-12 22:11:30.960: I/robin(26133): 1:java.lang.Thread.getStackTrace(Thread.java:745)
 
 
08-12 22:11:30.960: I/robin(26133): 2:
  com.lenovo.robin.test.MyService
  .
  onStartCommand
  (MyService.java:18)
 
 
08-12 22:11:30.960: I/robin(26133): 3:android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2456)
 
 
08-12 22:11:30.960: I/robin(26133): 4:android.app.ActivityThread.access$2800(ActivityThread.java:135)
 
 
08-12 22:11:30.960: I/robin(26133): 5:android.app.ActivityThread$H.handleMessage(ActivityThread.java:1127)
 
 
08-12 22:11:30.960: I/robin(26133): 6:android.os.Handler.dispatchMessage(Handler.java:99)
 
 
08-12 22:11:30.960: I/robin(26133): 7:android.os.Looper.loop(Looper.java:150)
 
 
08-12 22:11:30.960: I/robin(26133): 8:android.app
  .ActivityThread
  .main(
  ActivityThread.java:4385
  )
 
 
08-12 22:11:30.960: I/robin(26133): 9:java.lang.reflect.Method.invokeNative(Native Method)
 
 
08-12 22:11:30.960: I/robin(26133): 10:java.lang.reflect.Method.invoke(Method.java:507)
 
 
08-12 22:11:30.960: I/robin(26133): 11:com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
 
 
08-12 22:11:30.970: I/robin(26133): 12:com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
 
 
08-12 22:11:30.970: I/robin(26133): 13:dalvik.system.NativeStart.main(Native Method)
 
测试实例3 

  文件MainActivity.java

 
  
package
    com
   .
   lenovo
   .
   robin
   .
   test
   ;
  


  
  
import
    android
   .
   os
   .
   Bundle
   ;
  
import
    android
   .
   app
   .
   Activity
   ;
  
import
    android
   .
   content
   .
   Intent
   ;
  
import
    android
   .
   util
   .
   Log
   ;
  
import
    android
   .
   view
   .
   Menu
   ;
  
import
    android
   .
   view
   .
   MenuItem
   ;
  
import
    android
   .
   view
   .
   View
   ;
  
import
    android
   .
   support
   .
   v4
   .
   app
   .
   NavUtils
   ;
  


  
  
public
    
   class
    
   MainActivity
    
   extends
    
   Activity
    
   {
  
 
   static
    
   boolean
    iscreated
   =
   false
   ;
  
 
   final
    
   static
    
   String
    TAG
   =
   "robin"
   ;
  
    
   @Override
  
    
   public
    
   void
    onCreate
   (
   Bundle
    savedInstanceState
   )
    
   {
  
        
   super
   .
   onCreate
   (
   savedInstanceState
   );
  
        setContentView
   (
   R
   .
   layout
   .
   activity_main
   );
  
        iscreated
   =
   true
   ;
  
        
   Log
   .
   i
   (
   TAG
   ,
   "on create() in MainActivity"
   );
  
        
   this
   .
   startService
   (
   new
    
   Intent
   (
   this
   ,
   MyService
   .
   class
   ));
  
    
   }
  
    
   @Override
  
    
   public
    
   void
    onDestroy
   ()
    
   {
  
        
   Log
   .
   i
   (
   TAG
   ,
   "OnDestoryv in main"
   );
  
        
   super
   .
   onDestroy
   ();
  
        android
   .
   os
   .
   Process
   .
   killProcess
   (
   android
   .
   os
   .
   Process
   .
   myPid
   ());
  
        
   //System.exit(1);
  
    }
  
    public void onClick(View v)
  
    {
  
    
    
   StackTraceElement st[]= Thread.currentThread().getStackTrace();
  
    
    
   for(int i=0;i<st.length&&i<20;i++)
  
    
    
    Log.w(TAG,i+":"+st[i]);
  
    }
  
}
 

  文件layout\activity_main.xml

 
  
<RelativeLayout
    
   xmlns:android
   =
   "http://schemas.android.com/apk/res/android"
  
    
   xmlns:tools
   =
   "http://schemas.android.com/tools"
  
    
   android:layout_width
   =
   "match_parent"
  
    
   android:layout_height
   =
   "match_parent"
    
   >
  


  
  
    
   <TextView
  
        
   android:id
   =
   "@+id/textView1"
  
        
   android:layout_width
   =
   "wrap_content"
  
        
   android:layout_height
   =
   "wrap_content"
  
        
   android:layout_centerHorizontal
   =
   "true"
  
        
   android:layout_centerVertical
   =
   "true"
  
        
   android:text
   =
   "@string/hello_world"
  
        
   tools:context
   =
   ".MainActivity"
    
   />
  


  
  
    
   <Button
  
        
   android:id
   =
   "@+id/button1"
  
        
   android:layout_width
   =
   "wrap_content"
  
        
   android:layout_height
   =
   "wrap_content"
  
        
   android:layout_above
   =
   "@+id/textView1"
  
        
   android:layout_alignLeft
   =
   "@+id/textView1"
  
        
   android:layout_marginBottom
   =
   "46dp"
  
        
   android:layout_marginLeft
   =
   "44dp"
  
        
   android:text
   =
   "Button"
    
  
        
   android:onClick
   =
   "onClick"
   />
  


  
  
</RelativeLayout>
 

  运行结果:

 
08-17 08:22:36.755: W/robin(12413): 0:dalvik.system.VMStack.getThreadStackTrace(Native Method)
 
 
08-17 08:22:36.755: W/robin(12413): 1:java.lang.Thread.getStackTrace(Thread.java:745)
 
 
08-17 08:22:36.755: W/robin(12413): 2:com.lenovo.robin.test.MainActivity.onClick(MainActivity.java:32)
 
 
08-17 08:22:36.755: W/robin(12413): 3:java.lang.reflect.Method.invokeNative(Native Method)
 
 
08-17 08:22:36.755: W/robin(12413): 4:java.lang.reflect.Method.invoke(Method.java:507)
 
 
08-17 08:22:36.755: W/robin(12413): 5:android.view.View$1.
  onClick(
  View.java:2187)
 
 
08-17 08:22:36.755: W/robin(12413): 6:android.view.View.
  performClick
  (View.java:2533)
 
 
08-17 08:22:36.755: W/robin(12413): 7:android.view.View$PerformClick.run(View.java:9320)
 
 
08-17 08:22:36.755: W/robin(12413): 8:android.os.Handler.handleCallback(Handler.java:587)
 
 
08-17 08:22:36.755: W/robin(12413): 9:android.os.Handler.dispatchMessage(Handler.java:92)
 
 
08-17 08:22:36.755: W/robin(12413): 10:android.os.Looper.loop(Looper.java:150)
 
 
08-17 08:22:36.755: W/robin(12413): 11: