在应用TCP/IP协议进行数据传输的时候,经常用到的是IOCP的概念。我们经常试想如果HTTP的能够应用多线程的模式来进行数据的交互,将会给系统/应用带来更好的用户体验。通过线程访问WEB获取数据并将数据交给另一个线程处理是本节研究的重点。关于Handler、Looper、Message详细的原理可以参考其他文章。这里推荐《Android Looper和Handler分析》(见 http://www.linuxidc.com/Linux/2012-07/64095.htm)本人也是受到其启发,设计了一个简单的应用框架。
(1) 连接服务器获取控制指令;
(2) 执行服务器的命令;
(3) 返回执行结果;
系统设计总图如下图所示,系统由三个线程组成:主线程、连接服务器线程、数据处理线程。
主线程用来设置定时器,开启线程;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)
{
}
}
}