等了一晚上也沒有人回答,我自已就重新看了一遍代碼,發現我的思路是有問題的。
我在第二篇的代碼中,是這樣實現循環的:
我在主線程的run方法中調用handler.sendMessage(msg)
而在handler的sendMessage中使用 post方法將run放置在消息隊列中
這樣相互調用形成了一個循環
然後使用handler的removeCallbacks將run從消息隊列中去除,從而中斷跳出循環
這樣整個循環是在主線程的message queue中形成的。
而我在第三篇中,想要用新建的線程來實現計數的時候,仍然按照上面的思路來寫,就有個問題:當我在主線程中使用handler的post方法時,實際上是將新建線程中的run方法在主線程執行(放到主線程的message queue中)
這樣其實整個過程還是在主線程中運行的
經過一夜的思索,我突然意識到,我其實是要在新建的線程中實現計數的功能,那就應該讓循環在新建的線程中實現
於是我把代碼改成了下面的樣子
我在代碼中加入一個靜態的變量running,用於控制新線程中的循環計數
我在新線程中寫入一個循環,當running爲true時,循環計數,並調用handler.sendMessage(msg)爲主線程傳遞計數結果
package com.example.handler4;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
public class MainActivity extends Activity {
Button startButton = null;
Button stopButton = null;
ProgressBar progressbar = null;
Thread counter = null;
//線程執行的標誌,當爲true時,線程中繼續循環
static boolean running = true;
//獲取主線程的looper
Looper looper = Looper.getMainLooper();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startButton = (Button) findViewById(R.id.startButton);
stopButton = (Button) findViewById(R.id.stopButton);
progressbar = (ProgressBar) findViewById(R.id.progressBar);
//爲button綁定onclicklistener
startButton.setOnClickListener(new ButtonOnclickListener());
stopButton.setOnClickListener(new stopOnclickListener());
}
class ButtonOnclickListener implements OnClickListener{
public void onClick(View v) {
progressbar.setVisibility(View.VISIBLE);
counter = new Thread(){
int i = 1;
@Override
public void run() {
// TODO Auto-generated method stub
while(running){
i += 10;
Message msg = handler.obtainMessage();
msg.arg1 = i;
//讓線程延遲一秒
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
Log.i("run", "run "+i+"%");
Log.i("run", Thread.currentThread().getName());
msg.sendToTarget();
if(i>100)
//當計數超過一百時,跳出循環
running = false;
}
}
};
counter.start();
}
}
class stopOnclickListener implements OnClickListener{
public void onClick(View v) {
//點擊取消按鈕,分線程不再循環計數
running = false;
//讓progressbar置成隱藏
progressbar.setVisibility(View.GONE);
}
}
//將handler與主線程關聯
Handler handler = new Handler(looper){
public void handleMessage(android.os.Message msg) {
int i =msg.arg1;
//根據message中傳來的參數控制進度條
progressbar.setProgress(i);
Log.i("run", Thread.currentThread().getName());
if(i>100){
//如果進度條慢,進度條隱藏
progressbar.setVisibility(View.GONE);
}
};
};
}
後臺打印日誌的截圖:
這樣,問題基本解決了,感覺自己對多線程的理解還是太淺了,很多時候容易想當然的來也代碼,沒有深刻理解代碼背後的含義。還是要繼續努力啊,當然還是要說一句,根據網上大神的說法,在android中多線程更多的是用AsyncTask,而不是Thread和Handler去更新UI。接下來,我就開始學習AsyncTask的用法。