歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android多線程之Handler、Looper、Message在基於HTTP系統中的應用

1.背景

在應用TCP/IP協議進行數據傳輸的時候,經常用到的是IOCP的概念。我們經常試想如果HTTP的能夠應用多線程的模式來進行數據的交互,將會給系統/應用帶來更好的用戶體驗。通過線程訪問WEB獲取數據並將數據交給另一個線程處理是本節研究的重點。關於Handler、Looper、Message詳細的原理可以參考其他文章。這裡推薦《Android Looper和Handler分析》(見 http://www.linuxidc.com/Linux/2012-07/64095.htm)本人也是受到其啟發,設計了一個簡單的應用框架。

2.應用功能/任務

(1)    連接服務器獲取控制指令;

(2)    執行服務器的命令;

(3)    返回執行結果;

3.設計

系統設計總圖如下圖所示,系統由三個線程組成:主線程、連接服務器線程、數據處理線程。

3.1基本原理

主線程用來設置定時器,開啟線程;ConnectThread用來連接服務器,ConnectThread獲取的數據發送給DataProcessThread,而DataProcessThread則僅僅進行數據處理,數據處理完成之後,又通過Message將結果告知ConnectThread,由ConnectThread將處理結果返回給服務器。

也就是說,在整個過程中,與服務器進行數據交互的是ConnectThread,數據處理是DataProcessThread,並且僅僅是這樣。

線程ConnectThread和DataProcessThread的數據交互則通過Handler、Looper等接口來完成。ConnectThread和DataProcessThread各與一個私有的Looper和公共的Handler (分別設為handler1、handler2)綁定。

這裡要注意的是,線程不存在默認的Looper,只能自行創建。並且只能在線程內部創建。如下實例:為每個線程創建一個Handler的繼承類,而handleMessage則是進行數據提取的真正方法。

  1. //定義子線程類中的接收消息   
  2.     class ThreadHandler extends Handler{  
  3.           
  4.         public ThreadHandler(Looper looper){  
  5.             super(looper);  
  6.         }      
  7.         @Override        
  8.         public void handleMessage(Message msg) {    
  9.             switch (msg.what) {    
  10.             case  UPDATE_DATA://常量   
  11.              getData();    
  12.                 break;    
  13.             default:  
  14.                     break;    
  15.             }    
  16.         }    
  17.          
  18.     }  
  19.     //接收數據、處理線程   
  20.     private Thread ReceiveThread = new Thread(){      
  21.           
  22.         public void run()  
  23.         {     
  24.             Looper.prepare();  
  25.             //當前線程的Looper對象   
  26.             handler1=new ThreadHandler(Looper.myLooper());        
  27.             Looper.loop();   
  28.         }  
  29.     };  
  30.       


 

 

 

 

在兩個線程進行數據傳輸的時候,可以采取兩種方式:

①設置Request響應的全局變量Response,當ConnectThread請求到數據之後,通過handler2.sendEmptyMessage(int what)方法告知DataProcessThread,而DataProcessThread一旦接收到ConnectThread發來的空消息(因為是sendEmptyMessage發來的),則通過Response來獲取數據,並進行命令執行;

② ConnectThread利用包android.os.Handler中的obtainMessage (int what, int arg1, int arg2,Object obj)和sendMessage (Message msg)對接收數據直接進行封裝並發送給DataProcessThread,DataProcessThread再進行命令執��。

這兩種方法就好比,我們在取信件的時候有兩種方式一樣,一是人家告訴我,我自己去拿二人家直接給我送來;

測試代碼:(本人加入一些顯示界面)

  1. package home.handler;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.util.Timer;  
  8. import java.util.TimerTask;  
  9.   
  10. import org.apache.http.HttpEntity;  
  11. import org.apache.http.HttpResponse;  
  12. import org.apache.http.client.HttpClient;  
  13. import org.apache.http.client.methods.HttpGet;  
  14. import org.apache.http.impl.client.DefaultHttpClient;  
  15.   
  16.   
  17. import android.app.Activity;  
  18. import android.os.Bundle;  
  19. import android.os.Handler;  
  20. import android.os.Looper;  
  21. import android.os.Message;  
  22. import android.view.View;  
  23. import android.widget.Button;  
  24. import android.widget.EditText;  
  25.   
  26. public class PHPHandlerActivity extends Activity {  
  27.     protected static final int UPDATE_TEXT = 0;  
  28.     protected static final int RETURN_RESULT = 1;  
  29.     private Handler handler1,handler2,handler3;  
  30.     private EditText etGet;  
  31.     //private HttpPost request;   
  32.     //private HttpClient client;   
  33.     private HttpResponse response=null;  
  34.                           
  35.     /** Called when the activity is first created. */  
  36.     @Override  
  37.     public void onCreate(Bundle savedInstanceState) {  
  38.         super.onCreate(savedInstanceState);  
  39.         setContentView(R.layout.main);  
  40.         etGet = (EditText)findViewById(R.id.etGet);  
  41.          //按鈕函數:開啟線程   
  42.        final Button mThreadStartButton=(Button)findViewById(R.id.button1);  
  43.        mThreadStartButton.setOnClickListener(new Button.OnClickListener() {  
  44.           
  45.         @Override  
  46.         public void onClick(View v) {  
  47.             // TODO Auto-generated method stub   
  48.             ReceiveThread.start();  
  49.             Timer timer = new Timer();  
  50.             timer.schedule(new mTask(), 301000*60*2);   
  51.             mThreadStartButton.setEnabled(false);  
  52.         }  
  53.        });   
  54.     }  
  55.    
  56.     //*****************************************************************************************   
  57.     //從此處添加自定義函數   
  58.     //*****************************************************************************************   
  59.     class MyHandler extends Handler{  
  60.           
  61.         public MyHandler(Looper looper){  
  62.             super(looper);  
  63.         }  
  64.         @Override  
  65.         public void handleMessage(Message msg){  
  66.             super.handleMessage(msg);  
  67.             etGet.setText("主線程的Handler,收到了消息:"+(String)msg.obj);  
  68.         }  
  69.     }  
  70.     //返回執行結果Handler   
  71.     class ReturnHandler extends Handler{  
  72.           
  73.         public ReturnHandler(Looper looper){  
  74.             super(looper);  
  75.         }  
  76.         @Override  
  77.         public void handleMessage(Message msg){  
  78.             super.handleMessage(msg);  
  79.             switch (msg.what) {    
  80.             case  RETURN_RESULT:  
  81.                 phpweb();   
  82.                 break;    
  83.             default:  
  84.                     break;    
  85.             }    
  86.         }  
  87.     }  
  88.       
  89.     //定時器線程,連接服務器線程   
  90.      private class mTask extends TimerTask{  
  91.            
  92.          @Override    
  93.          public void run() {   
  94.              //連接服務器   
  95.              HttpResponse response=phpweb();  
  96.              if (response!=null)   
  97.                  handler1.sendEmptyMessage(UPDATE_TEXT);  
  98.                
  99.              Looper.prepare();  
  100.              //當前線程的Looper對象   
  101.              handler3=new ReturnHandler(Looper.myLooper());       
  102.              Looper.loop();   
  103.          }       
  104.      }    
  105.     //定義子線程類中的接收消息   
  106.     class ThreadHandler extends Handler{  
  107.           
  108.         public ThreadHandler(Looper looper){  
  109.             super(looper);  
  110.         }      
  111.         @Override        
  112.         public void handleMessage(Message msg) {    
  113.             switch (msg.what) {    
  114.             case  UPDATE_TEXT:  
  115.              getData();    
  116.                 break;    
  117.             default:  
  118.                     break;    
  119.             }    
  120.         }    
  121.          
  122.     }  
  123.     //接收數據、處理線程   
  124.     private Thread ReceiveThread = new Thread(){      
  125.           
  126.         public void run()  
  127.         {     
  128.             Looper.prepare();  
  129.             //當前線程的Looper對象   
  130.             handler1=new ThreadHandler(Looper.myLooper());        
  131.             Looper.loop();   
  132.         }  
  133.     };  
  134.       
  135.       
  136.     //數據流轉換為字符串   
  137.     private static String convertStreamToString(InputStream is) {  
  138.         BufferedReader reader = new BufferedReader(new InputStreamReader(is));  
  139.         StringBuilder sb = new StringBuilder();  
  140.         String line = null;  
  141.         try {  
  142.         while ((line = reader.readLine()) != null) {  
  143.         sb.append(line + "\r\n");  
  144.         }  
  145.         } catch (IOException e) {  
  146.         e.printStackTrace();  
  147.         } finally {  
  148.         try {  
  149.         is.close();  
  150.         } catch (IOException e) {  
  151.         e.printStackTrace();  
  152.         }  
  153.         }  
  154.         return sb.toString();  
  155.         }  
  156.     //訪問web函數   
  157.     private HttpResponse phpweb(){  
  158.   
  159.         try {         
  160.             HttpClient client = new DefaultHttpClient();      
  161.             String url = "http://www.linuxidc.com";  
  162.             HttpGet httpGetRequest=new HttpGet(url);  
  163.             //響應   
  164.             response = client.execute(httpGetRequest);  
  165.             return response;  
  166.         }  
  167.         catch (Exception e) {  
  168.             // TODO: handle exception   
  169.             e.printStackTrace();  
  170.         }  
  171.         return response;           
  172.     }  
  173.      
  174.     //獲取數據函數   
  175.     private void getData() {  
  176.         try  
  177.         {             
  178.             HttpEntity entity = response.getEntity();  
  179.             //返回值不為空   
  180.             if (entity != null) {  
  181.                   
  182.                 InputStream instream = entity.getContent();  
  183.                 String result = convertStreamToString(instream);  
  184.                 //將收到的數據返回給主界面:主線程--構造別人的Handler   
  185.                 handler2 = new MyHandler(Looper.getMainLooper());  
  186.                 Message msg2 = handler2.obtainMessage(1,1,1,result);        
  187.                 handler2.sendMessage(msg2);  
  188.   
  189.                 handler3.sendEmptyMessage(RETURN_RESULT);  
  190.             }     
  191.   
  192.         }  
  193.         catch (Exception e)  
  194.         {  
  195.         }  
  196.     }  
  197.       
  198. }  
Copyright © Linux教程網 All Rights Reserved