CallableとWaitDialogの組み合わせた時の挙動に関するご質問

134 views
Skip to first unread message

Akira Saito

unread,
Oct 31, 2011, 6:17:56 PM10/31/11
to android-g...@googlegroups.com
初めまして。rsoooと申します。

スレッドに関するプログラムに関してご質問させてください。
現在私は、CallableとFutureTaskを用いて以下のような処理を実装したいと考えています。

1.ある値を返す処理を別スレッド(FutureTask)で実行
2.上記のスレッド実行中はWaitDialogを表示
3.上記のスレッドの実行が完了したらWaitDialogを消去
4.別スレッドから受け取った値の処理

この処理を以下のようなコードで記述してみましたが、
FutureTaskのget()を呼び出すとWaitDialogが表示されなくなります。

スレッドに関する知識が浅くて恐縮なのですが、
何か原因等お分かりでしたらご教授願えないでしょうか。

よろしくお願い致します。

---以下プログラム

@Override
public void onResume(){
super.onResume();

Callable<String> postCallable = new Callable<String>(){
@Override
public String call(){
String ret = "";
try {
/*時間かかる処理 */
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ret = "some value";
return ret;
}
};

final ExecutorService scheduler = Executors.newFixedThreadPool(1);
final FutureTask<String> futureTask = new FutureTask<String>(postCallable);
scheduler.execute(futureTask);
final ProgressDialog waitDialog = new ProgressDialog(context);

Handler h = new Handler();
h.post(new Runnable(){

@Override
public void run() {
waitDialog.setMessage("waiting");
waitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
waitDialog.show();
}

});

try {
String s = futureTask.get();
Log.i("TEST", "get finish ");
waitDialog.dismiss();//ダイアログ終了

} catch (Exception e) {
e.printStackTrace();
}

}

元木

unread,
Nov 1, 2011, 12:51:20 PM11/1/11
to android-g...@googlegroups.com
こんばんは、元木です。

「時間かかる処理」が完了していない時点でFuture#get() を呼び出すと、処理がブロックされます。
提示いただいたソースコードの場合、UIスレッドがブロックされてしまうために、うまく動かないのかと。

というわけで、書き換えてみました。
ProgressDialog表示10秒後に、時間かかる処理の結果("some value")を、Toastで表示します。


    @Override
    public void onResume(){
        super.onResume();

        final ProgressDialog waitDialog = new ProgressDialog(this);
        final Handler h = new Handler();
        Runnable postRunnable = new Runnable(){
            @Override
            public void run(){
                try {
                        /*時間かかる処理 */
                        Thread.sleep(10000);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
                final String ret = "some value";
                h.post(new Runnable() {
                    @Override
                    public void run() {
                        waitDialog.dismiss();//ダイアログ終了
                        Toast.makeText(MainActivity.this, "ret = " + ret, Toast.LENGTH_LONG).show();
                    }
                });
            }
        };

        waitDialog.setMessage("waiting");
        waitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        waitDialog.show();
        
        ExecutorService scheduler = Executors.newSingleThreadExecutor();
        scheduler.submit(postRunnable);
    }

rsooo

unread,
Nov 2, 2011, 11:31:40 PM11/2/11
to 日本Androidの会
元木 様

お世話になっております。
返信ありがとうございます。

上述の方法を試したことろダイアログの起動と終了はできるのですが、
別スレッドで得られた結果(この場合"some value")をメインスレッド側で扱いたいのですがよい方法はないでしょうか。

イメージは以下のような流れになります。

public void onResume(){
・・・

waitDialog.setMessage("waiting");
waitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
waitDialog.show();
*

|
ExecutorService scheduler = Executors.newSingleThreadExecutor();
| ここの間にProgressDialogを表示
scheduler.submit(postRunnable);
|

|

*
//ProgressDialog消去
//ここでpostRunnableの結果を処理したい

}

要領を得ていない質問で申し訳ありません。
何か良い知恵等あればご教授お願い致します。

元木

unread,
Nov 3, 2011, 1:26:51 AM11/3/11
to android-g...@googlegroups.com
こんにちは、元木です。

別スレッドで得られた結果(この場合"some value")をメインスレッド側で扱いたいのですがよい方法はないでしょうか

Handler#post() に渡しているRunnable の中の処理(以下の2行)は、メインスレッド上で動いていますよ。

rsooo

unread,
Nov 3, 2011, 2:35:00 AM11/3/11
to 日本Androidの会
元木様

お世話になっております。

すいません、言葉足らずでした。
私が行いたいと思った内容は、あるスレッドを実行した場合、
スレッドの呼び出し元(先ほどの例ではonResumeメソッド)で
呼び出し結果を処理という流れなのですが、
このようなことは可能なのでしょうか。
(さらにスレッド実行中はダイアログを表示させる)

不可能(もしくはそのような実装を普通しない)のであれば
元木様の提示いただいた内容で対処したい思います。

よろしくお願い致します。

元木

unread,
Nov 3, 2011, 3:04:10 AM11/3/11
to android-g...@googlegroups.com

こんにちは、元木です。

onResume() のコードブロックの中で「時間のかかる処理」の
結果を使おうとすると、処理が完了するまでメインスレッドを

  ・ブロックするか、
・終了条件を満たすまでループさせる

必要が生じます。どちらもメインスレッドを止めることになるので、避けることをおすすめします。

あと、蛇足ですが、ベタにHandler やRunnable を使うのでは
なく、AsyncTask の利用を検討してみてはいかがでしょうか?
バックグラウンドで何か実行させるのに便利なAPIが
用意されてます。
コードの可読性も増すと思いますよ。

rsooo

unread,
Nov 3, 2011, 3:39:52 AM11/3/11
to 日本Androidの会
元木 様

お世話になっております。
お返事ありがとうございます。

なるほど、やはりうまいやり方ではないのですね。
AsyncTask ですね。知りませんでした。
リファレンス等を見て利用を検討させていただきます。

ご教授ありがとうございました。
Reply all
Reply to author
Forward
0 new messages