Java – Cyclically alters bitmap images

Cyclically alters bitmap images… here is a solution to the problem.

Cyclically alters bitmap images

I

have a Canvas and I want the bitmap image to change every 50 milliseconds.

Basically what I want to do is like an animated GIF.

As you can see, there are 4 images and I want it to change the image every 50 milliseconds.

The code below doesn’t work, I don’t know why.

protected void onDraw(final Canvas canvas) {

res = getResources();
    image = BitmapFactory.decodeResource(res, R.drawable.image_1);
    canvas.drawBitmap(image, 0, 0, paint);

new Thread(new Runnable() {

@Override
        public void run() {
            while (! Thread.interrupted())
                try {
                    Thread.sleep(50);
                    System.out.println("OK2");

time++;
                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

if (time == 1) {

image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_1);

canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();
                            }
                            if (time == 2) {
                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_2);

canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();

}

if (time == 3) {
                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_3);

canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();

}

if (time >= 4) {

time = 0;
                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_4);
                                canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();

}
                        }
                    });
                } catch (InterruptedException e) {

}
        }

}).start();
    super.onDraw(canvas);

}

Thanks in advance.

Solution

There are a couple of questions:

You are decoding the resource every time. decodeResource may not be fast enough to load an image within 50 milliseconds. It is faster to decode the frames once and store them in an array. For example:

Bitmap images[4];
void loadFrames()
{
    res = getResources();
    images[0] = BitmapFactory.decodeResource(res, R.drawable.image_1);
    images[1] = BitmapFactory.decodeResource(res, R.drawable.image_2);
    images[2] = BitmapFactory.decodeResource(res, R.drawable.image_3);
    images[3] = BitmapFactory.decodeResource(res, R.drawable.image_4);
}

Each call to onDraw() starts a new thread, which means that hundreds of threads will be created. Instead, you should create the thread only once. Inside the thread, increment the counter and set image to the correct frame, then call invalidate:

 Thread.sleep(50);
 time = (time + 1) % 4;
 image = images[time];
 ((Activity) context).runOnUiThread(new Runnable() {
      @Override
      public void run() {
          invalidate();
      }
 };

Then in onDraw(), draw on the Canvas with the current image:

 canvas.drawBitmap(image, 0, 0, paint);

Related Problems and Solutions