恥ずかしげもなく技術ブログ

プログラミング等について書いていきます.

別スレッドで処理した画像を定期的に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になったらループを停止している.