文档章节

Android多线程之Handler、Looper、Message在基于HTTP系统中的应用

AbrahamLeeJay
 AbrahamLeeJay
发布于 2014/07/12 00:00
字数 1261
阅读 36
收藏 1

Android多线程之Handler、Looper、Message在基于HTTP系统中的应用

1.背景

在应用TCP/IP协议进行数据传输的时候,经常用到的是IOCP的概念。我们经常试想如果HTTP的能够应用多线程的模式来进行数据的交互,将会给系统/应用带来更好的用户体验。通过线程访问WEB获取数据并将数据交给另一个线程处理是本节研究的重点。关于HandlerLooperMessage详细的原理可以参考其他文章。这里推荐《Android LooperHandler分析》(见 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,并且仅仅是这样。

线程ConnectThreadDataProcessThread的数据交互则通过HandlerLooper等接口来完成。ConnectThreadDataProcessThread各与一个私有的Looper和公共的Handler (分别设为handler1handler2)绑定。

这里要注意的是,线程不存在默认的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)对接收数据直接进行封装并发送给DataProcessThreadDataProcessThread再进行命令执行。

这两种方法就好比,我们在取信件的时候有两种方式一样,一是人家告诉我,我自己去拿二人家直接给我送来;

测试代码:(本人加入一些显示界面)

  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. }  

linux


© 著作权归作者所有

上一篇: android动画
AbrahamLeeJay
粉丝 21
博文 56
码字总数 105294
作品 0
武汉
高级程序员
私信 提问
android消息机制,异步和多线程

android消息机制,异步和多线程 前言 在xxxx1.92正式版的时候付费购买曾单独封装了一个流程PaymentFlow并继承于Handler,调用方只要依据这个流程创建流程实例并触发开始,实例即可依据设定的支付...

ZHL
2012/09/03
4.8K
0
Android之多线程工作-AsyncTask与handler

本文主要讲解下AsyncTask的使用以及Handler的应用 首先,我们得明确下一个概念,什么是UI线程。顾名思义,ui线程就是管理着用户界面的那个线程! android的ui线程操作并不是安全的,并且和用...

鉴客
2012/03/09
1K
0
Android之多线程工作-AsyncTask与handler

本文主要讲解下AsyncTask的使用以及Handler的应用 首先,我们得明确下一个概念,什么是UI线程。顾名思义,ui线程就是管理着用户界面的那个线程! android的ui线程操作并不是安全的,并且和用...

晨曦之光
2012/03/01
3.2K
0
Android Message机制的灵活应用

一、线程间通讯的Message机制 1、Message介绍 frameworks\base\core\java\android\Os\Message.java Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。Message中包含了...

长平狐
2012/09/03
120
0
Handler与Android多线程

下面是一段大家都比较熟悉的代码: Handler handler = new Handler(); handler.post(myThread); //使用匿名内部类创建一个线程myThread Runnable mythread = new Runnable() { public void r......

吴鹏辉
2012/04/13
1K
3

没有更多内容

加载失败,请刷新页面

加载更多

rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0
简述TCP的流量控制与拥塞控制

1. TCP流量控制 流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。...

鏡花水月
今天
9
0
OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
942
11
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部