要寫Android,難懂的多執行緒一定要給他搞懂
在Android當中,如果做超過5秒被系統強制關閉
(收到Application not Responsed簡稱ANR)
onCreate()如果做超過10秒就會跳ANR
所以繁重的事情不能在onCreate()裡頭做
有沒有解決辦法?? 就是Thread 中文叫執行緒
搞不清楚?
用現實的例子說明好了
Thread ==> 做工的工人
Runnable ==> 要做的工作事項 (工作說明書)
一般的Thread,工人請他來,指定工作給他做。做完就收工閃人回家
有一種Thread,他的性質比較不一樣
算是包月的那種特約駐點工人吧,要簽合約的(笑)
上班時間跟公務員一樣,就算沒事情做也要standby在那裡
這種工人他會有個經紀人幫他管要給他作的事
HandlerThread ==> 特約工人
Handler ==> 特約工人的經紀人
----------------------------------------------------------------------------------
回到程式,一般來說,Activity 執行的時候
會有個 UI Thread 或叫 main Thread
就是你程式本身原有的執行緒,管著畫面呈現.....等等事物
main Thread (或叫UI Thread)就是你的程式進入點
而main Thread,他也是個HandlerThread
可以給他一個Handler,做接收訊息之用
----------------------------------------------------------------------------------
(以下程式碼只是示意,要表達程式碼的邏輯概念
實際上在運行的時候,模擬器的畫面不會產生任何的變化
可以把它當範本使用,稍加修改)
package com.J_Test.HandlerAndThread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
publicclass main extends Activity {
/** Called when the activity is first created. */
//找到UI工人的經紀人,這樣才能派遣工作 (找到顯示畫面的UI Thread上的Handler)
private Handler mUI_Handler = new Handler();
//宣告特約工人的經紀人
private Handler mThreadHandler;
//宣告特約工人
private HandlerThread mThread;
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//聘請一個特約工人,有其經紀人派遣其工人做事 (另起一個有Handler的Thread)
mThread = new HandlerThread("name");
//讓Worker待命,等待其工作 (開啟Thread)
mThread.start();
//找到特約工人的經紀人,這樣才能派遣工作 (找到Thread上的Handler)
mThreadHandler=new Handler(mThread.getLooper());
//請經紀人指派工作名稱 r,給工人做
mThreadHandler.post(r1);
}
//工作名稱 r1 的工作內容
private Runnable r1=new Runnable () {
publicvoid run() {
// TODO Auto-generated method stub
//.............................
//做了很多事
//請經紀人指派工作名稱 r,給工人做
mUI_Handler.post(r2);
}
};
//工作名稱 r2 的工作內容
private Runnable r2=new Runnable () {
publicvoid run() {
// TODO Auto-generated method stub
//.............................
//顯示畫面的動作
}
};
@Override
protectedvoid onDestroy() {
super.onDestroy();
//移除工人上的工作
if (mThreadHandler != null) {
mThreadHandler.removeCallbacks(r1);
}
//解聘工人 (關閉Thread)
if (mThread != null) {
mThread.quit();
}
}
}
---------------
2011.10.17更新新版,請前往:
http://j796160836.pixnet.net/blog/post/29895257

不好意思~有個問題想請教您~ 我在A.Activity做了 //宣告 static Socket clientSocket; // 嘗試連接Server try { // 設定IP serverIp = InetAddress.getByName("10.0.2.2"); // 設定port int serverPort=6000; // 初始socket連接 clientSocket=new Socket(serverIp,serverPort); if(clientSocket.isConnected()){ // 初始化輸出網路串流 BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(clientSocket.getOutputStream())); // 傳送訊息到客戶端 bw.write("#"+nickname+"\n"); // 立即送出 bw.flush(); } } catch (IOException e) { // 出錯後顯示錯誤訊息 Toast.makeText(this, "遊戲連結失敗" , Toast.LENGTH_LONG).show(); } 然後B.Activity的地方 //宣告 private Socket clientSocket=GameRoom.clientSocket; //啟用執行緒 Thread t = new Thread(readData); t.start(); 測試的結果是 有下面這個 Thread t = new Thread(readData); t.start(); 模擬器就會錯誤 請問大大 是不是不能這樣使用呢?
你要不要弄一個測試專案我測看看
清楚明暸~~讚~~ 順道一提 //工作名稱 r2 的工作內容 <--應該是r1,不是r2
謝謝您,文章已修正
大大的教學真是棒!大推一下。
您好,打擾您 想請教一下, 在onCreate 裡,Thread 啟動, 等待訊息接受後,結束. 我利用另一支程式,傳送文字, 只傳了一次後(假設我傳 123456789 這一串文字. 當然socket_service有收到文字, 但也只接收到一次, 再接一次傳送訊息時,socket_service 就無法收到訊息. 好像是onCreate 啟動後,就只啟動一次Thread , 那如果我要做到隨時等待訊息接收,那麼要如何做到呢? 程式碼如下 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TV_A = (TextView) findViewById( R.id.TV_A ); TV_B = (TextView) findViewById( R.id.TV_B ); //建立Thread Thread fst = new Thread(socket_server); //啟動Thread fst.start(); } //取得IP private String getMyIp(){ //新增一個WifiManager物件並取得WIFI_SERVICE //WifiManager wifi_service = (WifiManager)getSystemService(WIFI_SERVICE); //取得wifi資訊 //WifiInfo wifiInfo = wifi_service.getConnectionInfo(); //取得IP,但這會是一個詭異的數字,還要再自己換算才行 //int ipAddress = wifiInfo.getIpAddress(); //利用位移運算和AND運算計算IP //String ip = String.format("%d.%d.%d.%d",(ipAddress & 0xff),(ipAddress >> 8 & 0xff),(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff)); String ip = "10.1.12.8"; return ip; } private Runnable socket_server = new Runnable(){ public void run(){ handler.post(new Runnable() { public void run() { TV_A.setText("Listening...." + getMyIp()); } }); Log.d("a", "a"); try{ //建立serverSocket serverSocket = new ServerSocket(6666); //等待連線 while (true) { //接收連線 Log.d("a1", "a1"); Socket client = serverSocket.accept(); Log.d("a2", "a2"); handler.post(new Runnable() { public void run() { TV_B.setText("Connected."); } }); try { //接收資料 Log.d("a3", "a3"); DataInputStream in = new DataInputStream(client.getInputStream()); line = in.readLine(); //in.readUTF(); Log.d("a4", "a4"); while (line != null) { handler.post(new Runnable() { public void run() { if (line != null) { TV_B.setText(line); } line = null; } }); } Log.d("a5", "a5"); client.close(); break; } catch (Exception e) { handler.post(new Runnable() { public void run() { TV_A.setText("傳送失敗"); } }); } } }catch(IOException e){ handler.post(new Runnable() { public void run() { TV_A.setText("建立socket失敗"); } }); } } }; }
看了很多地方總覺得似懂非懂的 直到看了您的文章 才豁然開朗:)
你的比喻很很貼切,謝謝你讓我搞清楚Handler與Thread的關係
有趣的比喻方式說明這樣更容易了解~
謝謝,很好的比喻!!
謝謝你的教學! 我有一個疑問是為什麼 private Handler mUI_handler = new Handler(); 可以是顯示畫面的UI Handler呢?