Android开发中的Handler线程初窥,及HandlerThread异步通信的实现。

来源:互联网 发布:python replace 正则 编辑:程序博客网 时间:2024/05/29 15:51

最近学习Android,学习的时候会用Java的一些机制去理解,但是往往还是有些区别的。


下面我们来看看Android下面的线程使用方法,这里通常会用到Handler。


Handler的作用就是一个队列,先进先出,实现了异步机制。


下面是这个工程的main.xml配置文件:(两个例子的使用同一个xml)

 

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ProgressBar  
  8. android:id = "@+id/bar"  
  9. style="?android:attr/progressBarStyleHorizontal"  
  10. android:layout_width = "200dp"  
  11. android:layout_height = "wrap_content"  
  12. android:visibility = "gone"  
  13. />  
  14. <Button  
  15. android:id = "@+id/startButton"  
  16. android:layout_width = "fill_parent"  
  17. android:layout_height ="wrap_content"  
  18. android:text = "start"  
  19. />  
  20. </LinearLayout>  
 



先来看看第一个例子:

[java] view plaincopy
  1. package com.cyl;  
  2. import android.app.Activity;  
  3. import android.os.*;  
  4. import android.widget.*;  
  5. import android.view.View;  
  6. import android.view.View.OnClickListener;  
  7. public class ProgressBarHandler extends Activity {  
  8.     private ProgressBar bar;  
  9.     private Button start;  
  10.     private Handler progressHandler;  
  11.     Runnable progressThread;  
  12.     @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.         //测试当前Activity线程  
  17.         //打印的结果是: Activity Thread : 1  
  18.         System.out.println("Activity Thread :" + Thread.currentThread().getId());  
  19.         bar = (ProgressBar)this.findViewById(R.id.bar);  
  20.         start = (Button)this.findViewById(R.id.startButton);  
  21.         //实现了Handler的内部类  
  22.         progressHandler = new Handler(){  
  23.             @Override  
  24.             public void handleMessage(Message msg) {  
  25.                 bar.setProgress(msg.arg1);  
  26.                 //经过证明Thread均是同一线程。  
  27.                 //打印的结果是: Handler Thread : 1  
  28.                 System.out.println("Handler Thread :" + Thread.currentThread().getId());  
  29.                 progressHandler.post(progressThread);  
  30.                 //模拟在90%时停止,removeCallbacks移除线程不能放在Runnable中,否则可能会出现Bug,无法移除。  
  31.                 if(msg.getData().getInt("percent") >= 90){  
  32.                     progressHandler.removeCallbacks(progressThread);  
  33.                 }  
  34.             }  
  35.         };  
  36.           
  37.         //当在程序启动的时候就调用Handler进行加载处理  
  38.         //并且线程的执行时间很长,且不可预测,那么程序就会处于一个假死状态  
  39.         //progressHandler.post(progressThread);  
  40.         start.setOnClickListener(new OnClickListener(){  
  41.             @Override  
  42.             public void onClick(View v) {  
  43.                 bar.setVisibility(ProgressBar.VISIBLE);  
  44.                 progressHandler.post(progressThread);  
  45.             }             
  46.         });  
  47.           
  48.         //实现了Runnable的内部类  
  49.         progressThread = new Runnable(){  
  50.             int percent = 0;  
  51.             @Override  
  52.             public void run() {  
  53.                 percent += 5;  
  54.                 //打印的结果是: Runnable Thread : 1  
  55.                 System.out.println("Runnable Thread :" + Thread.currentThread().getId());  
  56.                 //通过Message对象传递参数  
  57.                 Message msg = new Message();  
  58.                 Bundle bundle = new Bundle();  
  59.                 bundle.putInt("percent", percent);  
  60.                 msg.setData(bundle);  
  61.                 progressHandler.sendMessage(msg);  
  62.                 try{  
  63.                     System.out.println("sleep ...");  
  64.                     Thread.sleep(1000);  
  65.                     //当在onCreate方法开始就调用progressHandler.post()时,我们设置时间足够长,模拟假死状态。  
  66.                     //主线程处于等待状态,界面无法显示。  
  67.                     //Thread.sleep(10000);  
  68.                     System.out.println("wake up...");  
  69.                 }catch(Exception e){  
  70.                     e.printStackTrace();  
  71.                 }  
  72.             }  
  73.         };  
  74.           
  75.     }  
  76. }  
 


 

在上面的例子中,Thread使用的是同一个,按照Java的常理应该是不同的,但是这里确实是同一个,大家可以自己测试下。


Handler与主线程是同一线程时,如果程序在设计的时候需要线程初始化较长时间或者下载文件,这种情况下,主线程是出于等待状态的,甚至出现假死现象。


在cmd100.com的视频讲解中,mars老师也讲的很清楚了,我大部分是参考其源代码再做修改。


解决办法是是用HandlerThread类来创建独立于主线程的新线程,实现异步机制,不会影响到主线程的运行。

 

解决代码如下:

 

 

[java] view plaincopy
  1. package com.cyl;  
  2. import android.app.Activity;  
  3. import android.os.*;  
  4. import android.widget.*;  
  5. import android.view.View;  
  6. import android.view.View.OnClickListener;  
  7. public class ProgressBarHandlerThread extends Activity {  
  8.     /** Called when the activity is first created. */  
  9.     ProgressBar bar;  
  10.     Button start;  
  11.     MyHandler myHandler;  
  12.     Runnable progressThread;  
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.main);  
  17.         System.out.println("Activity Thread :" + Thread.currentThread().getId());  
  18.         bar = (ProgressBar)this.findViewById(R.id.bar);  
  19.         start = (Button)this.findViewById(R.id.startButton);  
  20.       //使用HandlerThread来实现真正的异步线程,不会与主线程公用线程了。  
  21.         HandlerThread handlerThread = new HandlerThread("handler_thread");  
  22.         //使用getLooper()方法之前,先调start()方法  
  23.         handlerThread.start();  
  24.         myHandler = new MyHandler(handlerThread.getLooper());  
  25.           
  26.         start.setOnClickListener(new OnClickListener(){  
  27.             @Override  
  28.             public void onClick(View v) {  
  29.                 bar.setVisibility(ProgressBar.VISIBLE);  
  30.                 myHandler.post(progressThread);  
  31.             }             
  32.         });  
  33.           
  34.         //实现了Runnable的内部类  
  35.         progressThread = new Runnable(){  
  36.             int percent = 0;  
  37.             @Override  
  38.             public void run() {  
  39.                 percent += 5;  
  40.                 //打印的结果是: Activity Thread : 8  
  41.                 System.out.println("Runnable Thread :" + Thread.currentThread().getId());  
  42.                 //通过Message对象传递参数  
  43.                 Message msg = new Message();  
  44.                 Bundle bundle = new Bundle();  
  45.                 bundle.putInt("percent", percent);  
  46.                 msg.setData(bundle);  
  47.                 myHandler.sendMessage(msg);  
  48.                 try{  
  49.                     Thread.sleep(1000);  
  50.                 }catch(Exception e){  
  51.                     e.printStackTrace();  
  52.                 }  
  53.             }  
  54.         };  
  55.     }  
  56.       
  57.     class MyHandler extends Handler{  
  58.         public MyHandler(Looper looper){  
  59.             super(looper);  
  60.         }  
  61.         @Override  
  62.         public void handleMessage(Message msg) {  
  63.             bar.setProgress(msg.arg1);  
  64.             //打印的结果是: MyHandler Thread : 8  
  65.             System.out.println("MyHandler Thread :" + Thread.currentThread().getId());  
  66.             myHandler.post(progressThread);  
  67.             if(msg.arg1 >= 90){  
  68.                 myHandler.removeCallbacks(progressThread);  
  69.             }  
  70.         }  
  71.     }  
  72.    
  73.       
  74. }  
 

 

最后感谢cmd100.com视频教程,整理出来,供大家参考使用。

原创粉丝点击