Android UI How to - Use background thread to do image processing








The following code shows how to Use background thread to do image processing.

Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5

Example

Main layout xml file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Scale Icon"
        android:onClick="onScaleClick" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Crop Icon"
        android:onClick="onCropClick" />
    
    <ImageView
        android:id="@+id/image_result"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center" />
</LinearLayout>

Main Activity Java code

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ImageView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
/*from  w  w  w  . j  a  v a 2 s  .co m*/
public class WorkerActivity extends Activity implements Handler.Callback {
    
    private ImageProcessor mWorker;
    private Handler mResponseHandler;
    
    private ImageView mResultView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mResultView = (ImageView) findViewById(R.id.image_result);
        mResponseHandler = new Handler(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mWorker = new ImageProcessor(this, mResponseHandler);
        mWorker.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mWorker.setCallback(null);
        mWorker.quit();
        mWorker = null;
    }
    @Override
    public boolean handleMessage(Message msg) {
        Bitmap result = (Bitmap) msg.obj;
        mResultView.setImageBitmap(result);
        return true;
    }
   
    public void onScaleClick(View v) {
        for(int i=1; i < 10; i++) {
            mWorker.scaleIcon(i);
        }
    }

    public void onCropClick(View v) {
        for(int i=1; i < 10; i++) {
            mWorker.cropIcon(i);
        }
    }
}
class ImageProcessor extends HandlerThread implements Handler.Callback {
    public static final int MSG_SCALE = 100;
    public static final int MSG_CROP = 101;

    private Context mContext;
    private Handler mReceiver, mCallback;
    
    public ImageProcessor(Context context) {
        this(context, null);
    }
    
    public ImageProcessor(Context context, Handler callback) {
        super("AndroidRecipesWorker");
        mCallback = callback;
        mContext = context;
    }

    @Override
    protected void onLooperPrepared() {
        mReceiver = new Handler(getLooper(), this);
    }
    
    @Override
    public boolean handleMessage(Message msg) {
        Bitmap source, result;
        int scale = msg.arg1;
        switch (msg.what) {
        case MSG_SCALE:
            source = BitmapFactory.decodeResource(mContext.getResources(),
                    R.drawable.ic_launcher);
            result = Bitmap.createScaledBitmap(source,
                    source.getWidth() * scale, source.getHeight() * scale, true);
            break;
        case MSG_CROP:
            source = BitmapFactory.decodeResource(mContext.getResources(),
                    R.drawable.ic_launcher);
            int newWidth = source.getWidth() / scale;
            result = Bitmap.createBitmap(source,
                    (source.getWidth() - newWidth) / 2, 0,
                    newWidth, source.getHeight());
            break;
        default:
            throw new IllegalArgumentException("Unknown Worker Request");
        }
        if (mCallback != null) {
            mCallback.sendMessage(Message.obtain(null, 0, result));
        }
        return true;
    }
    public void setCallback(Handler callback) {
        mCallback = callback;
    }
    public void scaleIcon(int scale) {
        Message msg = Message.obtain(null, MSG_SCALE, scale, 0, null);
        mReceiver.sendMessage(msg);
    }
    
    //Crop the icon in the center and scale the result to the specified value
    public void cropIcon(int scale) {
        Message msg = Message.obtain(null, MSG_CROP, scale, 0, null);
        mReceiver.sendMessage(msg);
    }
}