多執行緒通訊之Handler實現
阿新 • • 發佈:2019-02-01
在Android系統中,多執行緒之間傳遞訊息我們可以用Handler來實現
UI執行緒向子執行緒傳送訊息,子執行緒接收到訊息後處理
public class MainToWorkThreadActivity extends Activity {
private Handler handler;
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_to_work_thread);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 在主執行緒傳送訊息
System.out.println("onClick: "
+ Thread.currentThread().getName());
Message msg = handler.obtainMessage();
msg.what = 100 ;
handler.sendMessage(msg);
}
});
new Thread() {
@Override
// 線上程中處理主執行緒傳送的訊息物件
// 為什麼工作執行緒中需要Looper物件,而主執行緒不需要??
public void run() {
// 準備Looper物件
Looper.prepare();
// 在WorkThread當中生成一個Handler物件
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("handleMessage: " + Thread.currentThread().getName());
}
};
// 呼叫Looper的loop()方法之後,Looper物件將不斷的從訊息佇列中取出訊息物件,
// 然後呼叫handlerMessage()方法處理該訊息物件
// 如果訊息佇列中沒有物件,則該執行緒阻塞
Looper.loop();
}
}.start();
}
}
子執行緒向UI執行緒傳送訊息,UI執行緒接收訊息後處理
public class WorkToMainThreadActivity extends Activity {
private Button button1, button2, button3;
private ProgressBar progressBar;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maintoworkthread);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button3 = (Button) findViewById(R.id.button3);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setMax(100);
/*
* 在java中可有兩種方式實現多執行緒,一種是繼承Thread類,一種是實現Runnable介面;
* Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()
* 方法就可以實現多執行緒操作了,但是一個類只能繼承一個父類,這是此方法的侷限。 兩種實現方式的區別和聯絡:
*
* 在程式開發中只要是多執行緒肯定永遠以實現Runnable介面為主,因為實現Runnable介面相比繼承Thread類有如下好處:
* 1.避免點繼承的侷限,一個類可以繼承多個介面。 2.適合於資源的共享
*/
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 繼承Thread方法實現多執行緒
new Thread() {
@Override
public void run() {
System.out.println("button1.onClick.run: " + Thread.currentThread().getId()+ Thread.currentThread().getName());
try {
int i = 5;
while (i <= 100) {
sleep(500);
Message msg = handler.obtainMessage();
msg.arg1 = i;
handler.sendMessage(msg);
// 上面一行程式碼將訊息物件放置到訊息隊列當中
// 1.Looper將會從訊息隊列當中將訊息物件取出
// 2.Looper將會找到與訊息物件對應的Handler物件
// 3.Looper將會呼叫handler物件的handleMessage(Message msg)方法,用於處理訊息物件
i += 5;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
super.run();
}
}.start();
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*
* 在實際開發中一個多執行緒的操作很少使用Thread類,而是通過Runnable介面完成。
* 但是在使用Runnable定義的子類中沒有start()方法,只有Thread類中才有。
* 此時觀察Thread類,有一個構造方法:public Thread(Runnable targer)此構造方法接受Runnable的子類例項,
* 也就是說可以通過Thread類來啟動Runnable實現的多執行緒。(start()可以協調系統的資源)
*/
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("button2.onClick.run: " + Thread.currentThread().getId()+ Thread.currentThread().getName());
try {
int i = 10;
while (i <= 100) {
Thread.sleep(1000);
Message msg = handler.obtainMessage();
msg.arg1 = i;
handler.sendMessage(msg);
i += 10;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
});
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*
* Runnable物件和主使用者介面執行緒的ID是相同。在這個例子中,我們直接利用handler物件post了一個runnable物件
* ,相當於直接呼叫了Runnable物件的run函式,也就說沒有經過start函式呼叫run(),那麼就不會建立一個新執行緒,
* 而是在原有執行緒內部直接呼叫 run()方法,因此輸出的執行緒Id是相同的。
*/
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("button3.onClick.run: " + Thread.currentThread().getId()+ Thread.currentThread().getName());
try {
int i = 1;
while (i <= 100) {
Thread.sleep(100);
Message msg = handler.obtainMessage();
msg.arg1 = i;
handler.sendMessage(msg);
i += 1;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 在主執行緒處理訊息,工作執行緒傳送訊息,以方便執行緒間通訊
// 這樣可以解決工作執行緒不能操作UI的問題
System.out.println("handleMessage: " + Thread.currentThread().getId() + Thread.currentThread().getName());
progressBar.setProgress(msg.arg1);
super.handleMessage(msg);
}
};
}
}