基礎知識
- 多線程
- 消息機制
- 基於TCP協議的網絡通信
創建多線程的方法
- 一種是,繼承Thread類
Thread類代表線程類,它的兩個最主要的方法是:
run()——包含線程運行時所執行的代碼
Start()——用於啓動線程 - 另一種是,實現Runnable接口
實現Runnable接口,讓類實現Runnable接口,然後把run方法單獨提出來
兩種方法的區別:
- Callable、Future和FutureTask:在執行完線程之後可以返回執行結果
原文鏈接:http://www.cnblogs.com/dolphin0520/p/3949310.html
handle消息機制
- Android 消息處理機制(Looper、Handler、MessageQueue,Message)
原文鏈接:http://www.jianshu.com/p/02962454adf7 - Android 異步消息處理機制 讓你深入理解 Looper、Handler、Message三者關係
原文鏈接:http://blog.csdn.net/lmj623565791/article/details/38377229
Handler類的主要作用:
- 在新啓動的線程中發送消息 handler.sendMessage(msg);
- 在主線程中獲取、處理消息 public void handleMessage(Message msg)
- 消息的載體Message
基於TCP協議的網絡通信
SmartBed上位機控制APP指令傳送與接收採用TCP的sokect多線程
/**
* Description:指令傳送和接收的線程
* @author zhangjing
*
*/
public class SBClientThread implements Runnable
{
private Context context;
private String IPAddress;
private int ServerPort;
private boolean isRemoterServer;
private Socket s;
// 定義向UI線程發送消息的Handler對象
private Handler handler;
// 定義接收UI線程的消息的Handler對象
public Handler revHandler;
// 該線程所處理的Socket所對應的輸入流
InputStream is = null;
// 該線程所處理的Socket所對應的輸出流
OutputStream os = null;
/**
* 設備連接構造函數
* @param context
* @param handler
* @param iPString IP地址
* @param portString 端口號
*/
public SBClientThread(Context context, Handler handler,String iPString, String portString)
{
this.context = context;
this.handler = handler;
IPAddress = iPString;
ServerPort = Integer.parseInt(portString);
isRemoterServer = false;
}
/**
* 遠程服務器連接構造函數
* @param context
* @param handler
*/
public SBClientThread(Context context, Handler handler){
this.context = context;
this.handler = handler;
IPAddress = "xxxx.xxxx.xxxx.xxxx";//遠程服務器2
ServerPort = 8383;
isRemoterServer = true;
}
@Override
public void run() {
// TODO Auto-generated method stub
try
{
//Thread.sleep(1000);//線程暫停一秒
s = new Socket();
SocketAddress endpoint = new InetSocketAddress(IPAddress , ServerPort);
//設置連接超時時間
s.connect(endpoint, 5*1000);
//s = new Socket(IPAddress,ServerPoset);
is = s.getInputStream();
os = s.getOutputStream();
//輸出連接信息
if(s.isConnected()){
SBCommand.isConnect = true;
Message msg = new Message();
msg.what = 0x567;
//msg.obj = new String(s+"已連接!");
if(isRemoterServer){
//msg.obj = new String("遠程服務器連接成功 !\n\t\t\t\t\t [ "+s.getInetAddress().getHostAddress()+":"+s.getPort()+" ]");
msg.obj = new String("遠程服務器連接成功 !");
}else {
msg.obj = new String("設備連接成功 !\n\t\t\t\t\t [ "+s.getInetAddress().getHostAddress()+":"+s.getPort()+" ]");
}
handler.sendMessage(msg);
//提示
handler.post(new Runnable() {
@Override
public void run() {
if(isRemoterServer){
Toast.makeText(context.getApplicationContext(),"遠程服務器連接成功",
Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context.getApplicationContext(),"設備連接成功",
Toast.LENGTH_SHORT).show();
}
}
});
}
// 啓動一條子線程來讀取服務器響應的數據
new Thread()
{
@Override
public void run()
{
try
{
// 每當讀到來自服務器的數據之後,發送消息通知程序界面處理該數據
while(true){
int count = 0;
while (count == 0) {
count = is.available();
}
byte[] buffer = new byte[count];
is.read(buffer);
String revString = SBCommand.bytesToHexString(buffer);
//revString =" " + revString;
Message msg = new Message();
msg.what = 0x123;
msg.obj = revString;
handler.sendMessage(msg);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}.start();
// 爲當前線程初始化Looper
Looper.prepare();
// 創建revHandler對象
revHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
// 接收到UI線程中用戶輸入的數據
if (msg.what == 0x345)
{
// 將用戶在文本框內輸入的內容寫入網絡
// 接收到UI線程中用戶輸入的數據
try
{
String commString = null;
commString = msg.obj.toString();
os.write(SBCommand.hexStringToByte(commString));
os.flush();
}
catch (Exception e)
{
e.printStackTrace();
Message msg1 = new Message();
msg1.what = 0x789;
msg1.obj = new String("連接已斷開!");
handler.sendMessage(msg1);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context.getApplicationContext(),"指令發送失敗,請重新連接",
Toast.LENGTH_LONG).show();
}
});
}
}
}
};
// 啓動Looper
Looper.loop();
}
catch(SocketTimeoutException ex)
{
Message msg = new Message();
msg.what = 0x789;
msg.obj = new String("連接超時!");
handler.sendMessage(msg);
//SBClient.isConnect = false; 放在handler消息隊列中 ,以下同理
//提示
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context,"請檢查連接信息,重新連接",
Toast.LENGTH_SHORT).show();
}
});
}
catch (Exception e)
{
e.printStackTrace();
Message msg = new Message();
msg.what = 0x789;
msg.obj = new String("連接失敗!");
handler.sendMessage(msg);
//SBClient.isConnect = false;
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context.getApplicationContext(),"請檢查連接信息,重新連接",
Toast.LENGTH_SHORT).show();
}
});
}
}
/**
* 註銷Soket,關閉wifi
*/
public void onDestroy() {
//此程序影響UI線程,故增加新線程
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
try {
if(s!=null)
{
s.close();
s = null;
is.close();
is = null;
os.close();
os = null;
SBCommand.isConnect = false;
ProgressDialog.closeDialogProgress();
Message msg = new Message();
msg.what = 0x567;
msg.obj = new String("連接關閉成功!");
//注意:Toast在線程中需要消息機制
handler.sendMessage(msg);
//提示
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context.getApplicationContext(),"設備連接關閉成功",
Toast.LENGTH_SHORT).show();
}
});
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}