android 重い処理中にProgressDialogを表示し、中断もできるようにする

時間のかかる処理中に処理状況を示すダイアログを表示する必要がある場合は多いです。ProgressDialogを使えばいいのですが、終了時点での処理結果の表示と途中での処理の停止ができるようなサンプルコードを作成してみました。

Eclipseを使用しました。android 2.2(APIレベル8)です。





コードは以下の通りです。
ボタンを押すとボタンの文字列が「開始」に変わりダイアログが表示されます。
最後まで処理が終わるとダイアログが閉じて文字列が「終了」に変わります
途中でキャンセルボタンを押すとダイアログが閉じ処理が中断されます。ボタンの表示は「??で中断」に変わります。

dlg1.setCancelable(false);の設定で本体の戻るボタン(BACKボタン)でダイアログが閉じないようにしています。 ボタンでダイアログが閉じてもスレッドは動き続けるので、その状態を防ぐためです。

このコードで問題なのは、キャンセルボタンを押すとスレッドの処理が停止しなくてもダイアログが閉じることです。
もう少し検討が必要なようです。


main.xml layoutに置きます
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >


    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>



ProgressDialogActivity.java

package progress.dialog.namespace;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class ProgressDialogActivity extends Activity {
    private ProgressDialog dlg1 = null;
    boolean stop_thread=false;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        dlg1 = new ProgressDialog(this);
        // タイトル, 本文を設定
        dlg1.setTitle("プログレスバー");
        dlg1.setMessage("しばらくお待ちください.");
        // スタイルを設定
        dlg1.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        //dlg2.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dlg1.setCancelable(false);//本体の戻るボタンでのキャンセルを無効にする
        dlg1.setMax(100);
        //キャンセルボタン
        dlg1.setButton(getString(android.R.string.cancel), new DialogInterface.OnClickListener(){
			@Override
			public void onClick(DialogInterface dialog, int which) {
				stop_thread=true;//スレッド停止フラグを立てる。ダイアログの仕様上ダイアログ自体はスレッド終了を待たずにここで閉じる
			}});
        
        findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	((Button)v).setText("開始");
                dlg1.show();
                //スレッド開始
                stop_thread=false;
                Thread thread=new Thread(new Runnable() {
                    @Override
                    public void run() {
                    	int i=0;
                        try {
                            for( i=0; i<dlg1.getMax(); i++) {
                                // 進捗率を更新
                            	Log.d("ProgressDialog",""+i);//********
                                dlg1.setProgress(i);
                                Thread.sleep(100);
                                if(stop_thread){break;}//フラグが立つと終了する
                            }
                        } catch (InterruptedException e) {
                            // 例外処理
                        }
                        //handler.sendEmptyMessage(0);//メッセージを送る必要が無い場合
                    	Message msg= Message.obtain() ;//メッセージを送る処理
                    	if(stop_thread){msg.obj=i+"で中断";}
                    	else{msg.obj="終了";}
                        handler.sendMessage(msg);

                        /*
                         // こんな風に書くとここで落ちる
                        if(stop_thread){
                    		((Button)findViewById(R.id.button1)).setText("中断");}
                    	else{((Button)findViewById(R.id.button1)).setText("終了");}
                        dlg1.dismiss();
                        */
                    }
                });
                thread.start();
                //((Button)v).setText("終了");//ここに書くと処理が終わらなくても「終了」になる
                
            }
        });
        
        
    }
    private Handler handler = new Handler() {
        public void handleMessage(Message msg){
        	Log.d("Handler","msg.obj="+msg.obj);//********
        	((Button)findViewById(R.id.button1)).setText((CharSequence) msg.obj);
     
            // プログレスダイアログ終了
        	dlg1.dismiss();
        }
    };
    
}






TOPに戻る
2012/5/2