誤區一:(線程阻塞)
private void button1_click() throws InterruptedException {
AlertDialog dialog = new AlertDialog.Builder(this)
.setMessage("加載中...")
.show();
Thread.sleep(5000);
button1.setText("加載完畢");
dialog.dismiss();
}
????????以上代碼,很多人描述看到的效果是:點擊按鈕后,彈出一個對話框,顯示“加載中...”,5秒后按鈕顯示文字變成了“加載完畢”,對話框消失。
????????但是以上描述是錯誤的,你根本看不到對話框,你會發現事實上是這樣的:點擊按鈕后,按鈕沒有抬起來,5秒后,按鈕抬起來了,同時按鈕文字變成了“加載完畢”。
????????我們發現原來整個過程中,AlertDialog毫無存在感,根本也看不到它出現,原因是因為,這里發生了UI線程阻塞。當要show出dialog的時候,下一句是Thread.sleep(5000),這句話的意思是,當前的線程睡眠5秒,也就是UI線程,因為這句代碼沒有寫在子線程中,如果它寫在了子線程中,那么睡眠的就是子線程了,而非主線程。當睡眠完后,馬上修改按鈕的文字,再讓dialog消失,dialog的整個顯示到消失,排除掉睡眠時間,肉眼根本無法捕捉到。
????????如果我們真的要達到很多人描述的那種效果,我們需要這樣修改(且不說代碼嵌套層次和優化):
private void button1_click() throws InterruptedException {
AlertDialog dialog = new AlertDialog.Builder(this)
.setMessage("加載中...")
.show();
new Thread(new Runnable() {
@Override
public void run() {
Thread.sleep(5000);
runOnUiThread(new Runnable() {
@Override
public void run() {
button1.setText("加載完畢");
dialog.dismiss();
}
});
}
}).start();
}
誤區二:(cpu對線程的調度)
private void button1_click(View view) {
final AlertDialog dialog = new AlertDialog.Builder(this)
.setMessage("加載中...")
.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
runOnUiThread(new Runnable() {
@Override
public void run() {
button1.setText("加載完畢1");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
button1.postDelayed(new Runnable() {
@Override
public void run() {
button1.setText("加載完畢2");
dialog.dismiss();
}
},3000);
}
????????以上代碼,很多人描述看到的效果是:點擊按鈕后,彈出一個對話框,顯示“加載中…”,5秒后,按鈕文字變成了“加載完畢1”,又停了3秒后,按鈕問題變成了“加載完畢2”,對話框消失。
????????同樣,以上描述也是錯誤的。我們可以理解線程的開啟,就是一個任務塊的開啟,打開一個任務的開啟,并不需要花費cpu什么時間,同樣的,postDelayed也只是通知cpu,3秒后開啟一個任務,也是不需要花多少時間的,至于具體去處理這些任務的時候,那又是另一個層面的事情,不會影響當前的代碼執行順序,也就是說,整個代碼塊,我們可以理解為在UI線程中,只給cpu下達了三個命令:彈出一個對話框,開一個子線程執行一個任務,3秒后執行一個任務。
????????所以,我們看到的效果應該是:點擊按鈕后,彈出一個對話框,顯示“加載中…”,3秒后,按鈕問題變成了“加載完畢2”,對話框消失,又過了2秒后,按鈕文字變成了“加載完畢1”。