網上有很多關於progressdialog的用法的介紹,下面這個是最具代表性的:
http://sd8089730.iteye.com/blog/1441610
其核心代碼:
Handler handler = new Handler(); Runnable mTasks = new Runnable() { public void run() { //執行url獲取內容操作 } }; final ProgressDialog myDialog = ProgressDialog.show(YourClass.this, "正在連接服務器..", "連接中,請稍后..", true, true); handler.post(mTasks);
我實際使用后的效果是:點擊按鈕后(我是把這一系列操作放在一個clicklistener里)UI界面就阻塞在那里,然后等task執行完畢之后才顯示progressdialog並且一直會存在(當然如果你在這個task結束后添加一條dialog.dismiss語句就會發現progressdialog顯示后立即就消失了,但是這個不是本文的重點)我在stackoverflow上發現不少人有同樣的問題,但是並沒有找到正確的答案,只是有人給出了asynctask類的方案(我沒有實際使用這個方案,但是根據我最后的理解,這種方案應該也是可行的)
這個問題困擾了我一個下午的時間,要解釋這個問題,就要簡單說一下android的UI線程,android程序啟動時,會啟動一個對應的主線程(就是UI線程),這個線程負責和用戶的交互(例如按下按鈕,滑動等),我們只能在UI線程中訪問android UI 工具包。但是對於一些很耗時的操作,如果我們在主線程里完成的話,主線程就不能響應用戶的操作,這樣就會產生類似windows程序失去響應的效果,所以大部分時候我們都會啟動一個新的線程執行這些操作,但是要注意在新的線程里是不能修改UI界面的(只能在UI線程里修改UI界面)。比如說我們想下載一個url的html內容,然后顯示在界面的一個Textview上,我們如果在新啟動的線程里調用textview.settext()方法是不會生效的。
說了這么多,是為了說明handler的作用就是為了在其他線程里更新UI。比如我們如果用handler.post(run) (run的內容就是更新在textview)的話,就可以實現我們的目的。
回到正題,我們如果按照前述代碼使用progressdialog的話,在執行完
final ProgressDialog myDialog = ProgressDialog.show(YourClass.this, "正在連接服務器..", "連接中,請稍后..", true, true);
這條語句之后
handler.post(mTasks);
這條語句雖然看起來是在mtask這個線程里執行,但是因為使用了handler類,所以效果實際還是等同於阻塞了UI線程。所以progressdialog就等到mtask執行完畢之后才顯示了。因此我們正確的寫法應該是這樣的:
final ProgressDialog myDialog = ProgressDialog.show(YourClass.this, "正在連接服務器..", "連接中,請稍后..", true, true); new Thread(){ public void run() { //執行url獲取內容操作 handle.post( //在這里面更新textview); } }.start();
最后如果希望在新線程執行完之后讓progressdialog自動消失的話,就在新線程里利用handler執行dialog.dismiss()。這個內容在本文開頭的鏈接里也有詳細的介紹,在這里就不贅述了。