tags:

views:

531

answers:

1

I've created an application that show around 250 images in ImageView. Images are loaded one after another, 15-30 images per second. Basically the whole thing gives an illusion of a rotating 3D object, at least it should. The problem is next, app hangs when loading certain images(i.e. I see a few seconds of fluid animation and then animation hangs, jump 10-15 frames(images) ahead and continues. It always happens at the same places in animation cycle. I though that Android might not have enough resources to handle something like this, so I've resized images to half their size, but it did't help. I've tried buffering images but that did't help either(actually, maybe a little, I think that animation looks a little bit smoother). And now the weirdest thing. I use the touch screen to allow users to "rotate" the 3D object on those images, and while rotating I again experience those hangs at exactly the same places as with the animation.

All images are in .png format and their size vary from 15kB to 40kB.

I use the following code for the animation:

new Thread(new Runnable() {

   @Override
   public void run() {
    while (!stopStartupAnimation && li < images_360.length) {
     final int fli = li;
     handler.post(new Runnable() {

      @Override
      public void run() {
       //Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
       //imageCanvas.setImageResource(images_360[fli]);
       imageCanvas.setImageBitmap(imageStackNext.pop());
       System.out.println("rawX = " + fli);
      }
     });
     int ti = fli +25;
     if(ti > images_360.length-1){
      ti = ti - images_360.length;
     }
     imageStackNext.push(BitmapFactory.decodeResource(getResources(), images_360[ti]));
     synchronized (this) {
      try {
       wait(1000 / 25);
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
     }
     li++;
     li++;
     if (li >= images_360.length) {
      li = 0;
     }
    }
   }
  }).start();
A: 

First, 15-40KB is their compressed form. Uncompressed, as Bitmaps, they are probably substantially larger. 250 of them may be using many MB of RAM, which is not a good idea.

Second, given a choice between using OpenGL for 3D (which is its purpose), or the 2D drawing primitives on the Canvas, or using ImageView, you chose the worst-performing option.

Third, postRunnable() does not take effect immediately, but rather puts things on a message queue for the main application thread to process when it gets a chance. If it gets tied up -- say, handling touch events -- it may well skip over some seemingly redundant ImageView redraws, or have them go by so fast they appear to not happen. All your 40ms wait() does is ensure that you are only raising events every 40ms, not that they will paint every 40ms. Besides, you could have more easily just used postDelayed() for your 40ms timing.

CommonsWare
Images are not loaded all at once, but one by one. You are right about OpenGL but using it for this application would be an overkill, since object I'm animating isn't a cube or something simple, plus there is more to it than just this object.I know that postRunnable() doesn't take effect immediately and I've tried to use postDelayed() but it produces the same effect.
Milan
Further, I've already wrote that I've tried resizing the images to half their size and that it did't help. What I've failed to say is that when I use the touch screen to rotate the 3D object(by swiping the touch screen) it doesn't matter if I rotate it by 360' or by 10' the hangs are still present at exactly the same place where they occurred in animation.
Milan
"You are right about OpenGL but using it for this application would be an overkill, since object I'm animating isn't a cube or something simple" So, you think the way to efficiently implement a not-simple 3D animation is to avoid the 3D hardware-accelerated technology and use a worse-performing alternative? "I know that postRunnable() doesn't take effect immediately and I've tried to use postDelayed() but it produces the same effect." Of course it will -- both of them put events on the main thread's queue. That's unavoidable when using widgets, which is why 3D animations shouldn't use widgets.
CommonsWare
This is not a 3D animation. Essentially it is a frame-by-frame(2D) animation, but the images I'm using give an impression of 3D when animated. I could just as easily use some other random images instead of these I'm using now, which will not give an impression of third dimension.I appreciate you help, but it looks like you are trying to force me to use OpenGL. Which is not possible for more reasons than one.
Milan
Fine. Then either use a real frame-by-frame animation (`AnimationDrawable`) or draw the images to the `Canvas` directly to try avoiding some overhead. Or use the tools in DDMS to track your memory allocations and try to eliminate all of them during the animation, to eliminate GC as a culprit. Or take a look at the nearly 7000 lines of code that make up `ListView` (and `AbsListView`), all designed to make things smooth, and figure out how to apply those techniques to your code. Also, be sure to test this on hardware, because the emulator lacks HW acceleration.
CommonsWare
Thanks for your advices. Garbage Collector is the one to blame for the animation hangs.
Milan