layout/ ui.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <ImageView
- android:id="@+id/ProgressDialogSample_ImageView_pImg"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:background="@drawable/progress_circular_background"
- />
- <ProgressBar
- android:id="@+id/ProgressDialogSample_ProgressBar_pBar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:visibility="invisible"
- />
- <TextView
- android:id="@+id/ProgressDialogSample_TextView_desc"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/ProgressDialogSample_ProgressBar_pBar"
- android:text="未執行任何步驟。"
- />
- </RelativeLayout>
主程式
- package iamshiao.sample;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.widget.ImageView;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- public class ProgressDialogSample extends Activity {
- private final int step1 = 1, step2 = 2, step3 = 3, finish = 4;
- private Thread thread = null;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ui);
- //建構執行緒
- thread = new Thread(){
- @Override
- public void run(){
- try{
- doStep1();
- doStep2();
- doStep3();
- Thread.sleep(3000);
- Message msg = new Message();
- msg.what = finish;
- uiMessageHandler.sendMessage(msg);
- }catch (Exception e){
- e.printStackTrace();
- }finally{
- }
- }
- };
- //開始執行執行緒
- thread.start();
- }
- private void doStep1() throws InterruptedException{
- Thread.sleep(3000);
- Message msg = new Message();
- msg.what = step1;
- uiMessageHandler.sendMessage(msg);
- }
- private void doStep2() throws InterruptedException{
- Thread.sleep(3000);
- Message msg = new Message();
- msg.what = step2;
- uiMessageHandler.sendMessage(msg);
- }
- private void doStep3() throws InterruptedException{
- Thread.sleep(3000);
- Message msg = new Message();
- msg.what = step3;
- uiMessageHandler.sendMessage(msg);
- }
- //宣告Handler並同時建構隱含類別實體
- Handler uiMessageHandler = new Handler(){
- @Override
- public void handleMessage(Message msg){
- //讀出ui.xml中的進度光棒
- final ProgressBar pBar =
- (ProgressBar)findViewById(
- R.id.ProgressDialogSample_ProgressBar_pBar);
- pBar.setVisibility(View.VISIBLE); //開始後設為可見
- //讀出ui.xml中用以表示未開始的圖案
- final ImageView pImg =
- (ImageView)findViewById(R.id.ProgressDialogSample_ImageView_pImg);
- pImg.setVisibility(View.INVISIBLE); //開始後設為不可見
- //讀出ui.xml中的描述用TextView
- TextView tv =
- (TextView)findViewById(R.id.ProgressDialogSample_TextView_desc);
- switch (msg.what){
- case step1:
- tv.setText(R.string.processing_step1);
- break;
- case step2:
- tv.setText(R.string.processing_step2);
- break;
- case step3:
- tv.setText(R.string.processing_step3);
- break;
- case finish:
- tv.setText(R.string.finish);
- pBar.setVisibility(View.INVISIBLE);
- pImg.setVisibility(View.VISIBLE);
- tv.setText("完成。");
- thread.interrupt();
- break;
- }
- super.handleMessage(msg);
- }
- };
- }
執行緒的部分與前篇大致相同,但由於其中不能直接執行
這類UI View存取的動作,所以加入了Handler來控制UI View,Handler的運作是利用handleMessage這個事件來監聽執行緒是否有送出Message,如果有的話利用Message的what屬性等機制來判別要進行什麼動作。 例如程式碼中我宣告了4個常數
- tv.setText(R.string.processing_step1);
- private final int step1 = 1, step2 = 2, step3 = 3, finish = 4;
表示執行緒進行的步驟進度,而執行緒執行副程式doStep1~3的這個過程中,副程式在sleep完成後就會利用Handler變數的sendMessage來送出對應其步驟的Message變數。
- private void doStep1() throws InterruptedException{
- Thread.sleep(3000);
- Message msg = new Message();
- msg.what = step1;
- uiMessageHandler.sendMessage(msg);
- }
最後handleMessage事件再接聽到sendMessage之後就利用Message變數的what屬性之類的機制來判讀、執行對應動作。
- //宣告Handler並同時建構隱含類別實體
- Handler uiMessageHandler = new Handler(){
- @Override
- public void handleMessage(Message msg){
- ...
- switch (msg.what){
- case step1:
- tv.setText(R.string.processing_step1);
- break;
- ...
- }
- super.handleMessage(msg);
- }
- };
重點提醒,使用Thread&Handler要特別注意...
- handleMessage必須有@Override標註表示覆寫。
- 每個Message變數必須重新new,只改動what內容仍會被視為同樣的Message,而造成非預期的錯誤。
- Thread.sleep(3000);
- Message msg = new Message();
- msg.what = step1;
- uiMessageHandler.sendMessage(msg);
- Thread.sleep(3000);
- msg.what = step2; //X 同Message實體只變更what就重複使用會造成非預期錯誤。
- uiMessageHandler.sendMessage(msg);
- Thread.sleep(3000);
- msg = new Message(); //O Message有重新建構實體才正確。
- msg.what = step3;
- uiMessageHandler.sendMessage(msg);
補充
Message變數也可以透過setData方法來攜帶Bundle實體傳遞資料。
- Message msg = new Message();
- Bundle data = new Bundle();
- data.putString("data", "data");
- msg.setData(data);
- msg.what = step2;
- uiMessageHandler.sendMessage(msg);
- case step2:
- tv.setText(msg.getData().getString("data"));
完整專案下載
您的範例非常受用,非常感謝您的講解:)
回覆刪除從中獲益匪淺,謝謝您
回覆刪除找為什麼使用progress dialog的時候程式會crash的原因時,看到這篇好文,一再修改後,終於可以在程式中使用progress dialog了!謝謝iam$hiao的詳細解說
回覆刪除學習了, 謝謝您~
回覆刪除讚~ 很清楚 終於有點小小的瞭解
回覆刪除http://stackoverflow.com/questions/17372814/conversion-between-message-and-string-in-android
回覆刪除這也很清楚
網誌管理員已經移除這則留言。
回覆刪除網誌管理員已經移除這則留言。
刪除