別スレッドで処理した画像を定期的にImageViewに反映する
時間がかかる処理をメインスレッド(ここでは,Activityがうごくスレッドとする)の中に組み込んでしまうと,GUIの更新が停止してしまい,androidではアプリを停止しますか?という警告が出てしまう.
そこで通常はUIを扱うスレッドとは別のスレッドで時間のかかる処理を行う.
この記事ではメインスレッドとは別に
(1)定期的にImageViewを再描画するスレッド <- UIを扱う ただしメインスレッドではない
(2)画像処理を行うスレッド <- UIは扱わない 主に時間がかかるスレッド
を同時に動かし,(2)が終了したら(1)のスレッドも停止させることを実現する.
# ただし,そもそもSurfaceViewを用いるとSurfaceView自体が別スレッドなので(1)と(2)のように分けずonDraw()メソッドの中で完結できるということも知っておこう.
まず,Activityのフィールドに
private Bitmap image;
private boolean isFinished;
を追加し,onCreateとか適当なところに以下の処理を書く.
// (2) 画像処理など時間がかかる処理を行うスレッド
new Thread(new Runnable() {
@Override
public void run() {
/*画像処理*/
ImageProc.foo(image)
isFinished = true;
}
}).start();
// (1) UIを担当するスレッド
/* 定期的に画像処理の結果を描画する */
final Handler handler = new Handler();
handler.post( new Runnable() {
@Override
public void run() {
try {
ImageView iv = (ImageView) findViewById(R.id.imageView);
iv.setImageBitmap(image);
iv.invalidate();
handler.postDelayed(this,100);
if (isFinished){
handler.removeCallbacks(this);
}
}catch(Exception e){}
}
});
handler.postDelayed(this,100);
は100msで自身を呼び出すコード.すぐ下のコードでは
isFinishedがtrueになったらループを停止している.