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則是進行數據提取的真正方法。
- //定義子線程類中的接收消息
- class ThreadHandler extends Handler{
-
- public ThreadHandler(Looper looper){
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case UPDATE_DATA://常量
- getData();
- break;
- default:
- break;
- }
- }
-
- }
- //接收數據、處理線程
- private Thread ReceiveThread = new Thread(){
-
- public void run()
- {
- Looper.prepare();
- //當前線程的Looper對象
- handler1=new ThreadHandler(Looper.myLooper());
- Looper.loop();
- }
- };
-
在兩個線程進行數據傳輸的時候,可以采取兩種方式:
①設置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再進行命令執��。
這兩種方法就好比,我們在取信件的時候有兩種方式一樣,一是人家告訴我,我自己去拿二人家直接給我送來;
測試代碼:(本人加入一些顯示界面)
- package home.handler;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.Timer;
- import java.util.TimerTask;
-
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpResponse;
- import org.apache.http.client.HttpClient;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.impl.client.DefaultHttpClient;
-
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Message;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
-
- public class PHPHandlerActivity extends Activity {
- protected static final int UPDATE_TEXT = 0;
- protected static final int RETURN_RESULT = 1;
- private Handler handler1,handler2,handler3;
- private EditText etGet;
- //private HttpPost request;
- //private HttpClient client;
- private HttpResponse response=null;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- etGet = (EditText)findViewById(R.id.etGet);
- //按鈕函數:開啟線程
- final Button mThreadStartButton=(Button)findViewById(R.id.button1);
- mThreadStartButton.setOnClickListener(new Button.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- ReceiveThread.start();
- Timer timer = new Timer();
- timer.schedule(new mTask(), 30, 1000*60*2);
- mThreadStartButton.setEnabled(false);
- }
- });
- }
-
- //*****************************************************************************************
- //從此處添加自定義函數
- //*****************************************************************************************
- class MyHandler extends Handler{
-
- public MyHandler(Looper looper){
- super(looper);
- }
- @Override
- public void handleMessage(Message msg){
- super.handleMessage(msg);
- etGet.setText("主線程的Handler,收到了消息:"+(String)msg.obj);
- }
- }
- //返回執行結果Handler
- class ReturnHandler extends Handler{
-
- public ReturnHandler(Looper looper){
- super(looper);
- }
- @Override
- public void handleMessage(Message msg){
- super.handleMessage(msg);
- switch (msg.what) {
- case RETURN_RESULT:
- phpweb();
- break;
- default:
- break;
- }
- }
- }
-
- //定時器線程,連接服務器線程
- private class mTask extends TimerTask{
-
- @Override
- public void run() {
- //連接服務器
- HttpResponse response=phpweb();
- if (response!=null)
- handler1.sendEmptyMessage(UPDATE_TEXT);
-
- Looper.prepare();
- //當前線程的Looper對象
- handler3=new ReturnHandler(Looper.myLooper());
- Looper.loop();
- }
- }
- //定義子線程類中的接收消息
- class ThreadHandler extends Handler{
-
- public ThreadHandler(Looper looper){
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case UPDATE_TEXT:
- getData();
- break;
- default:
- break;
- }
- }
-
- }
- //接收數據、處理線程
- private Thread ReceiveThread = new Thread(){
-
- public void run()
- {
- Looper.prepare();
- //當前線程的Looper對象
- handler1=new ThreadHandler(Looper.myLooper());
- Looper.loop();
- }
- };
-
-
- //數據流轉換為字符串
- private static String convertStreamToString(InputStream is) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(is));
- StringBuilder sb = new StringBuilder();
- String line = null;
- try {
- while ((line = reader.readLine()) != null) {
- sb.append(line + "\r\n");
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return sb.toString();
- }
- //訪問web函數
- private HttpResponse phpweb(){
-
- try {
- HttpClient client = new DefaultHttpClient();
- String url = "http://www.linuxidc.com";
- HttpGet httpGetRequest=new HttpGet(url);
- //響應
- response = client.execute(httpGetRequest);
- return response;
- }
- catch (Exception e) {
- // TODO: handle exception
- e.printStackTrace();
- }
- return response;
- }
-
- //獲取數據函數
- private void getData() {
- try
- {
- HttpEntity entity = response.getEntity();
- //返回值不為空
- if (entity != null) {
-
- InputStream instream = entity.getContent();
- String result = convertStreamToString(instream);
- //將收到的數據返回給主界面:主線程--構造別人的Handler
- handler2 = new MyHandler(Looper.getMainLooper());
- Message msg2 = handler2.obtainMessage(1,1,1,result);
- handler2.sendMessage(msg2);
-
- handler3.sendEmptyMessage(RETURN_RESULT);
- }
-
- }
- catch (Exception e)
- {
- }
- }
-
- }