在Android上以高帧率绘制高分辨率动画

时间:2011-01-18 13:03:33

标签: android animation opengl-es canvas

我有30多个单位图(320x240像素)我希望在Android设备上全屏显示,从而产生动画效果。目前,我使用ImageView和Timer实现动画,设置下一帧,然后发送将应用下一帧的消息。得到的帧速率非常低:< 2 fps。

计时器:

animationTimer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        Drawable frame = getNextFrame();
            if (frame != null) {
                Message message = animationFrameHandler.obtainMessage(1, frame);
                animationFrameHandler.sendMessage(message);
            }
        }
    }, 0, (int) (1000.0d / fps));

处理程序:

final Handler animationFrameHandler = new Handler() {
    @Override
    public void handleMessage(Message message) {
        setImageDrawable((Drawable) message.obj);
    }
};

由于我想要达到最高30 fps的帧速率,我必须使用另一种机制并听说 Canvas.drawBitmapMesh() OpenGL

如果可能,我想避免使用OpenGL。

非常感谢您分享您的经历!

4 个答案:

答案 0 :(得分:5)

我现在的工作方法如下:

在开始动画之前,将每一帧加载到List<Bitmap>。重要提示:如果您获得System.gc(),请致电OutOfMemoryError - 这确实有助于将更多位图加载到内存中。然后运行一个线程,将下一帧发布到View实例,然后更新它的画布。

加载帧并开始动画

// Loading the frames before starting the animation
List<Bitmap> frames = new ArrayList<Bitmap>();
for (int i = 0; i < 30; i++) {
    // Load next frame (e. g. from drawable or assets folder)
    frames.add(...);
    // Do garbage collection every 3rd frame; really helps loading all frames into memory
    if (i %% 3 == 0) {
        System.gc();
    }
}

// Start animation
frameIndex = 0;
animationThread.start();

应用下一帧的主题

private final class AnimationThread extends Thread {
    @Override
    public void run() {
        while (!isInterrupted()) {
            // Post next frame to be displayed
            animationView.postFrame(frames.get(frameIndex));

            // Apply next frame (restart if last frame has reached)
            frameIndex++;
            if (frameIndex >= frames.size()) {
                frameIndex = 0;
            }

            try {
                sleep(33); // delay between frames in msec (33 msec mean 30 fps)
            } catch (InterruptedException e) {
                break;
            }
        }
    }
}

动画视图

class AnimationView extends View {
    Bitmap frame = null;

    public void postFrame(Bitmap frame) {
        Message message = frameHandler.obtainMessage(0, frame);
        frameHandler.sendMessage(message);
    }

    protected final Handler frameHandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            if (message.obj != null) {
                frame = (Bitmap) message.obj;
            } else {
                frame = null;
            }
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (frame == null) return;
        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawBitmap(frame, null, null, null);
    }
}

答案 1 :(得分:2)

你应该看一下FrameAnimation类; http://developer.android.com/guide/topics/graphics/2d-graphics.html#frame-animation使用Androids动画制作帧动画。

虽然这可能仍然太慢。

如果您不想使用OpenGL ES,另一种选择是按照您的提及绘制到Canvas。但是只使用.drawBitmap,而不是drawBitmapMesh。创建一个SurfaceView,它有一个线程,线程应该以你想要的任何间隔在你的Canvas上绘制。

这很简单,只需阅读Android文档,信息就在那里。

答案 2 :(得分:0)

我会让其他人采用最好的方式做到这一点,但有一件事从您的帖子中立刻跳到脑海,但没有帮助使用TimerTask是一种可怕的方法来做到这一点并不适用于动画。

答案 3 :(得分:0)

可能无法帮助提高性能,但如果这些位图是资源,您可能需要考虑使用AnimationDrawable。如果没有,请尝试扩展Drawable并实现Animatable接口。视图已经内置了对drawables动画的支持,不需要使用处理程序。

提高性能的一种方法可能是将drawable的位深度与当前窗口的位深度相匹配。 Romain Guy一般就这个和动画做了一次主题演讲:http://www.youtube.com/watch?v=duefsFTJXzc