zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Linux_修改网卡名
    综合架构_ansible_剧本编写
    综合架构_ansible自动化管理服务
    Linux_综合架构_ssh基于密钥_远程连接
    NFS项目实践
    综合架构_实时同步服务 inotify
    综合架构_nfs常见错误
    linux_知识点集锦
    企业全网备份数据
    综合架构_存储服务nfs
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/3241741.html
Copyright © 2011-2022 走看看