要寫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();
模擬器就會錯誤
請問大大 是不是不能這樣使用呢?
版主回覆:(09/24/2011 05:17:56 PM)
你要不要弄一個測試專案我測看看
清楚明暸~~讚~~ 順道一提
//工作名稱 r2 的工作內容 <–應該是r1,不是r2
版主回覆:(08/13/2012 06:31:41 AM)
謝謝您,文章已修正
大大的教學真是棒!大推一下。
您好,打擾您
想請教一下, 在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呢?