2016/05/31

[android]AsyncTaskとキャンセル

私が持っているAndroidの本には載っていないのだが、今は非同期で動かすというか、ワーカースレッドみたいにして動かしやすいようにAsyncTaskなるものがあるそうだ。

 

使い方はそこまで難しくなく、ネットに出てくるサンプル通りに書けば動いた。
しばらく非同期部分を動かしたかったので無限ループにすると、通らないルートが発生するためか怒られた。
適当にif文とbreakを追加すると言われなくなったのだが、そんな対応でよいのだろうか。。。

 

無限ループも、ぐるぐる回すと忙しすぎるので、Thread.sleep()で10秒ごとに回すようにした。
さて、そのときに非同期部分をキャンセルさせたかったら、どうするとよいのだろうか?

 

最初に試したのは、フラグだった。
停止フラグを用意して、ボタンを押したらフラグを立てる。
無限ループ内では停止フラグを見るようにして、立っていたらbreakで抜ける。
まあ、動くには動くのだが、sleepしている間は待っておくしかないので、ちょっとわびしい。

どうやら、Thread.sleep()は、Thread.interrupted()を呼ぶと抜けるらしい。
シグナルみたいなものか。

 

そうしていくうちに、isCancelled()があることに気付いた。
AsyncTaskを継承するとcancel()が追加され、これを呼んでやるとisCancelled()が立つので、無限ループでもこれでbreakすればよいようだ。

cancel()を呼ぶと、onCancelled()が呼び出されるようになっている。
じゃあ、さっきのThread.interrupted()をここで呼んでやるようにしておこう。

が、そこまでしなくても、cancel(true)としてやるとThread.interrupted()が呼ばれるようになっているみたいだ。
「mayInterruptIfRunning」では、わからんかったなぁ。
"thread"はAsyncTaskのことを指しているのかと思っていたよ。。


DDMS...じゃなくて、Android Device Monitorでアプリのスレッドを見ると、AsyncTaskをnewしていくとこういう風に見えた。

image

doInBackground()を抜けても数は変わらなかったが、StatusがWaitになった。
ArrayList<>に保持していたものもclear()しているから、消えると思ったんだけどね。
まだGCのタイミングじゃないと言うことか。
あるいは、1つずつ消さないといけないのか。。。
  • ArrayList#clear()だけ
    • 残ったまま
  • さらに=nullもする
    • 残ったまま
Android Device Monitorから「Cause GC」としても残っているので、消える対象になっていないのだろうという気がする。
うーん、この辺りをどうしてよいのか思いつかないところが哀しいですな。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。