Looper分析。ThreadLocal有关

     Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one,

call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

 1 class LooperThread extends Thread {
 2       public Handler mHandler; 
 4       public void run() {
 5           Looper.prepare(); 
 7           mHandler = new Handler() {
 8               public void handleMessage(Message msg) {
 9                   // process incoming messages here
10               }
11           };
13           Looper.loop();
14       }
15   }

(1)提出问题:正如上面所说, 一个线程默认是没有Looper用来处理message队列的。但为什么我们在主线程时又没有自己创建Looper呢?  

    

 1 public class Looper {
 2     private static final String TAG = "Looper";
 3 
 4     // sThreadLocal.get() will return null unless you've called prepare().
 5     static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();      //(1)又见到了眼熟的ThreadLocal,里面存放的是每个线程的Looper
 6     private static Looper sMainLooper;  // guarded by Looper.class
 7 
 8     final MessageQueue mQueue;
 9     final Thread mThread;
10     volatile boolean mRun;
11 
12     private Printer mLogging;
13 
14      /** Initialize the current thread as a looper.
15       * This gives you a chance to create handlers that then reference
16       * this looper, before actually starting the loop. Be sure to call
17       * {@link #loop()} after calling this method, and end it by calling
18       * {@link #quit()}.
19       */
20     public static void prepare() {
21         prepare(true);
22     }
23 
24     private static void prepare(boolean quitAllowed) {
25         if (sThreadLocal.get() != null) {
26             throw new RuntimeException("Only one Looper may be created per thread");
27         }
28         sThreadLocal.set(new Looper(quitAllowed));
29     }
30 
31     /**
32      * Initialize the current thread as a looper, marking it as an
33      * application's main looper. The main looper for your application
34      * is created by the Android environment, so you should never need
35      * to call this function yourself.  See also: {@link #prepare()}
36      */
37     public static void prepareMainLooper() {
38         prepare(false);
39         synchronized (Looper.class) {
40             if (sMainLooper != null) {
41                 throw new IllegalStateException("The main Looper has already been prepared.");
42             }
43             sMainLooper = myLooper();                                                       //(2)为主线程的Looper赋值
44         }
45     }
46 
47     /** Returns the application's main looper, which lives in the main thread of the application.
48      */
49     public static Looper getMainLooper() {
50         synchronized (Looper.class) {
51             return sMainLooper;
52         }
53     }
54 
55   
56     /**
57      * Return the Looper object associated with the current thread.  Returns
58      * null if the calling thread is not associated with a Looper.
59      */
60     public static Looper myLooper() {                                               //(3)为主线程Looper赋值的其实就是调用ThreadLocal的get()
61         return sThreadLocal.get();
62     }
63 
64    
65 }

2.如果不知道ThreadLocal是什么意思,自己去查API,我没这么大气和你讲。

3.所以我们可以这样用:

 1 public class MainActivity extends Activity {
 2     
 3         
 4       private ProgressDialog mpDialog;  
 5         private int mCount = 0;  
 6         
 7     private Handler handler = new Handler(){
 8 
 9         @Override
10         public void handleMessage(Message msg) {
11             //update UI
12              System.out.println("----------update ui ok--------------"+Thread.currentThread().getId());   // Thread id 为1 说明在主线程中执行。
13              System.out.println("message arg1 : "+ msg.arg1);                                        //因为这是主线程,所以可以在这时更新UI
14             super.handleMessage(msg);
15         }
16     };
17     
18     private Thread downThread = new Thread(){
19 
20         @Override
21         public void run() {          
22             
23              try{  
24                  while(mCount<=100){  
25                      mpDialog.setProgress(mCount++);  
26                      Thread.sleep(100);                                            //模拟下载过程
27                  }  
28                  // This is essentially the same as calling dismiss(), 
29                  //but it will also call your DialogInterface.OnCancelListener (if registered).
30                  mpDialog.cancel();  
31                  System.out.println("------------download ok----------");
32                  Message message = handler.obtainMessage();
33                  message.arg1 = 10;
34                  handler.sendMessage(message);
35              }catch(Exception ex){  
36                  mpDialog.cancel();  
37              }  
38         }
39         
40     };
41 
42     @Override
43     protected void onCreate(Bundle savedInstanceState) {
44         super.onCreate(savedInstanceState);
45         setContentView(R.layout.activity_main);
46         Button button= (Button) this.findViewById(R.id.button);
47         imageView = (ImageView) this.findViewById(R.id.imageView01);
48         button.setOnClickListener(new OnClickListener(){
49 
50             @Override
51             public void onClick(View view) {
52                     System.out.println("--------------download start----------------"+Thread.currentThread().getId());   //主线程的id为1
53                     mCount = 0;  
54                     mpDialog = new ProgressDialog(MainActivity.this);  
55                     mpDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
56                     mpDialog.setTitle("dialogʾ");  
57                     mpDialog.setIcon(R.drawable.ic_launcher);  
58                     mpDialog.setMessage("好消息");  
59                     mpDialog.setMax(100);  
60                     mpDialog.setProgress(0);  
61                     mpDialog.setSecondaryProgress(50);  
62                     mpDialog.setIndeterminate(false);  
63                     mpDialog.setCancelable(true);  
64                     mpDialog.setButton("取消", new DialogInterface.OnClickListener(){  
65       
66                         @Override  
67                         public void onClick(DialogInterface dialog, int which) {  
68                             dialog.cancel();  
69                               
70                         }  
71                           
72                     }); 
73                     downThread.start();
74                     mpDialog.show();
75             }
76             
77         });
78     }
79 
80 }

 4.正如上面所说,一个新线程在默认情况下是没有Looper相关联的。所以需要自己创建。但android提供了一个HandlerThread,方便我们使用Looper。

 1 public class HandlerThread extends Thread {
 2    
 3     Looper mLooper;
 4 
 5     
 6     /**
 7      * Call back method that can be explicitly overridden if needed to execute some
 8      * setup before Looper loops.
 9      */
10     protected void onLooperPrepared() {
11     }
12 
13     public void run() {
14         mTid = Process.myTid();
15         Looper.prepare();
16         synchronized (this) {
17             mLooper = Looper.myLooper();
18             notifyAll();
19         }
20         Process.setThreadPriority(mPriority);
21         onLooperPrepared();
22         Looper.loop();
23         mTid = -1;
24     }
25     
26     /**
27      * This method returns the Looper associated with this thread. If this thread not been started
28      * or for any reason is isAlive() returns false, this method will return null. If this thread 
29      * has been started, this method will block until the looper has been initialized.  
30      * @return The looper.
31      */
32     public Looper getLooper() {
33         if (!isAlive()) {
34             return null;
35         }
36         
37         // If the thread has been started, wait until the looper has been created.
38         synchronized (this) {
39             while (isAlive() && mLooper == null) {
40                 try {
41                     wait();
42                 } catch (InterruptedException e) {
43                 }
44             }
45         }
46         return mLooper;
47     }
48     
49  
50 }

 

 

 

posted @ 2013-08-06 19:42  等风来。。  Views(600)  Comments(0Edit  收藏  举报
------------------------------------------------------------------------------------------------------------ --------------- 欢迎联系 x.guan.ling@gmail.com--------------- ------------------------------------------------------------------------------------------------------------