我有个问题。我用逐帧动画编写了用于Android的动态壁纸,并且我已经完成了动画,但是动画播放的速度非常慢,大约每秒1帧。

这是我的代码

    public class WallpaperSer extends WallpaperService {

    static final Handler mHandler = new Handler();

    public void onCreate() {
        super.onCreate();
    }

    public void onDestroy() {
        super.onDestroy();
    }

    public Engine onCreateEngine() {
        return new WallpaperSerEngine();
    }

    class WallpaperSerEngine extends Engine  {
        private boolean mVisible;
        private float mScaleX;
        private float mScaleY;
        private Bitmap icon;
        private Runnable diwaliImg;

        int i = 0;
        int[] pirates = {
                R.drawable.final_0001,
                R.drawable.final_0002,
                R.drawable.final_0003,
                R.drawable.final_0004,
                R.drawable.final_0005,
                R.drawable.final_0006,
                R.drawable.final_0007,
                R.drawable.final_0008,
                R.drawable.final_0009,
                R.drawable.final_0010,
                R.drawable.final_0011,
                R.drawable.final_0012,
                R.drawable.final_0013,
                R.drawable.final_0014,
                R.drawable.final_0015,
                R.drawable.final_0016,
                R.drawable.final_0017,
                R.drawable.final_0018,
                R.drawable.final_0019,
                R.drawable.final_0020,
                R.drawable.final_0021,
                R.drawable.final_0022,
                R.drawable.final_0023,
                R.drawable.final_0024,
                R.drawable.final_0025,
                R.drawable.final_0026,
                R.drawable.final_0027,
                R.drawable.final_0028,
                R.drawable.final_0029,
                R.drawable.final_0030,
                R.drawable.final_0031,
                R.drawable.final_0032,
                R.drawable.final_0033,
                R.drawable.final_0034,
                R.drawable.final_0035,
                R.drawable.final_0036,
                R.drawable.final_0037,
                R.drawable.final_0038,
                R.drawable.final_0039,
                R.drawable.final_0040,
                R.drawable.final_0041,
                R.drawable.final_0042,
                R.drawable.final_0043,
                R.drawable.final_0044,
                R.drawable.final_0045,
                R.drawable.final_0046,
                R.drawable.final_0047,
                R.drawable.final_0048,
                R.drawable.final_0049,
                R.drawable.final_0050,
                R.drawable.final_0051,
                R.drawable.final_0052,
                R.drawable.final_0053,
                R.drawable.final_0054,
                R.drawable.final_0065,
                R.drawable.final_0056,
                R.drawable.final_0057,
                R.drawable.final_0058,
                R.drawable.final_0059,
                R.drawable.final_0060,
                R.drawable.final_0061,
                R.drawable.final_0062,
                R.drawable.final_0063,
                R.drawable.final_0064,
                R.drawable.final_0065,
                R.drawable.final_0066,
                R.drawable.final_0067,
                R.drawable.final_0068,
                R.drawable.final_0069,
                R.drawable.final_0070,
                R.drawable.final_0071,
                R.drawable.final_0072,
                R.drawable.final_0073,
                R.drawable.final_0074,
                R.drawable.final_0075,
                R.drawable.final_0076,
                R.drawable.final_0077,
                R.drawable.final_0078,
                R.drawable.final_0079,
                R.drawable.final_0080,
                R.drawable.final_0081,
                R.drawable.final_0082,
                R.drawable.final_0083,
                R.drawable.final_0084,
                R.drawable.final_0085,
                R.drawable.final_0086,
                R.drawable.final_0087,
                R.drawable.final_0088,
                R.drawable.final_0089,
                R.drawable.final_0090,
                R.drawable.final_0091,
                R.drawable.final_0092,
                R.drawable.final_0093,
                R.drawable.final_0094,
                R.drawable.final_0095,
                R.drawable.final_0096,
                R.drawable.final_0097,
                R.drawable.final_0098,
                R.drawable.final_0099,
                R.drawable.final_0100,
                R.drawable.final_0101,
                R.drawable.final_0102,
                R.drawable.final_0103,
                R.drawable.final_0104,
                R.drawable.final_0105,
                R.drawable.final_0106,
                R.drawable.final_0107,
                R.drawable.final_0108,
                R.drawable.final_0109,
                R.drawable.final_0110,
                R.drawable.final_0111,
                R.drawable.final_0112,
                R.drawable.final_0113,
                R.drawable.final_0114,
                R.drawable.final_0115,
                R.drawable.final_0116,
                R.drawable.final_0117,
                R.drawable.final_0118,
                R.drawable.final_0119,
                R.drawable.final_0120
        };

        WallpaperSerEngine() {
            diwaliImg = new Runnable() {
                public void run() {
                    drawFrame();
                }
            };
        }

        @Override
        public void onCreate(SurfaceHolder holder){
            super.onCreate(holder);
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacks(diwaliImg);
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            mVisible = visible;
            if (visible) {
                drawFrame();
            } else {
                mHandler.removeCallbacks(diwaliImg);
            }
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            super.onSurfaceChanged(holder, format, width, height);
            drawFrame();
            mScaleX = width / (1f * icon.getWidth());
            mScaleY = height / (1f * icon.getHeight());
        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            mVisible = false;
            mHandler.removeCallbacks(diwaliImg);
        }


        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, float xStep,float yStep, int xPixels, int yPixels) {
            drawFrame();
        }

        @Override
        public void onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
        }

        private void drawFrame() {
            final SurfaceHolder holder = getSurfaceHolder();
            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {
                    drawPirate(c);
                }
            } finally {
                if (c != null)
                    holder.unlockCanvasAndPost(c);
            }
            mHandler.removeCallbacks(diwaliImg);
            if (mVisible) {
                mHandler.postDelayed(diwaliImg, 1000 / 25);
            }
        }

        private void drawPirate(Canvas c) {
            icon = BitmapFactory.decodeResource(getResources(), pirates[i]);
            i++;
            if (i == 120) {
                i = 0;
            }
            Matrix matrix = new Matrix();
            c.scale(mScaleX, mScaleY);
            c.drawBitmap(icon, matrix, null);
            icon.recycle();
        }
    }
}


我做错了什么?

更新1
我的错误日志带有@chipopo代码:


  java.lang.IllegalArgumentException:解码到现有的问题
  位图
              在android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:482)
              在dajver.com.framebyframelivewallpaper.WallpaperSer $ WallpaperSerEngine.setToFrame(WallpaperSer.java:188)
              在dajver.com.framebyframelivewallpaper.WallpaperSer $ WallpaperSerEngine.drawPirate(WallpaperSer.java:266)
              在dajver.com.framebyframelivewallpaper.WallpaperSer $ WallpaperSerEngine.drawFrame(WallpaperSer.java:253)
              在dajver.com.framebyframelivewallpaper.WallpaperSer $ WallpaperSerEngine.onSurfaceChanged(WallpaperSer.java:219)
              在android.service.wallpaper.WallpaperService $ Engine.updateSurface(WallpaperService.java:783)
              在android.service.wallpaper.WallpaperService $ Engine.attach(WallpaperService.java:890)
              在android.service.wallpaper.WallpaperService $ IWallpaperEngineWrapper.executeMessage(WallpaperService.java:1157)
              在com.android.internal.os.HandlerCaller $ MyHandler.handleMessage(HandlerCaller.java:37)
              在android.os.Handler.dispatchMessage(Handler.java:102)
              在android.os.Looper.loop(Looper.java:135)
              在android.app.ActivityThread.main(ActivityThread.java:5221)
              在java.lang.reflect.Method.invoke(本机方法)
              在java.lang.reflect.Method.invoke(Method.java:372)
              在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:899)
              在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)


和我的代码与@chipppo编写的修复程序

public class WallpaperSer extends WallpaperService {

    static final Handler mHandler = new Handler();

    public void onCreate() {
        super.onCreate();
    }

    public void onDestroy() {
        super.onDestroy();
    }

    public Engine onCreateEngine() {
        return new WallpaperSerEngine();
    }

    class WallpaperSerEngine extends Engine  {
        private boolean mVisible;
        private float mScaleX;
        private float mScaleY;
        private Bitmap icon;
        private Runnable diwaliImg;

        int i = 0;
        int[] pirates = {
                R.drawable.final_0001,
                R.drawable.final_0002,
                R.drawable.final_0003,
                R.drawable.final_0004,
                R.drawable.final_0005,
                R.drawable.final_0006,
                R.drawable.final_0007,
                R.drawable.final_0008,
                R.drawable.final_0009,
                R.drawable.final_0010,
                R.drawable.final_0011,
                R.drawable.final_0012,
                R.drawable.final_0013,
                R.drawable.final_0014,
                R.drawable.final_0015,
                R.drawable.final_0016,
                R.drawable.final_0017,
                R.drawable.final_0018,
                R.drawable.final_0019,
                R.drawable.final_0020,
                R.drawable.final_0021,
                R.drawable.final_0022,
                R.drawable.final_0023,
                R.drawable.final_0024,
                R.drawable.final_0025,
                R.drawable.final_0026,
                R.drawable.final_0027,
                R.drawable.final_0028,
                R.drawable.final_0029,
                R.drawable.final_0030,
                R.drawable.final_0031,
                R.drawable.final_0032,
                R.drawable.final_0033,
                R.drawable.final_0034,
                R.drawable.final_0035,
                R.drawable.final_0036,
                R.drawable.final_0037,
                R.drawable.final_0038,
                R.drawable.final_0039,
                R.drawable.final_0040,
                R.drawable.final_0041,
                R.drawable.final_0042,
                R.drawable.final_0043,
                R.drawable.final_0044,
                R.drawable.final_0045,
                R.drawable.final_0046,
                R.drawable.final_0047,
                R.drawable.final_0048,
                R.drawable.final_0049,
                R.drawable.final_0050,
                R.drawable.final_0051,
                R.drawable.final_0052,
                R.drawable.final_0053,
                R.drawable.final_0054,
                R.drawable.final_0065,
                R.drawable.final_0056,
                R.drawable.final_0057,
                R.drawable.final_0058,
                R.drawable.final_0059,
                R.drawable.final_0060,
                R.drawable.final_0061,
                R.drawable.final_0062,
                R.drawable.final_0063,
                R.drawable.final_0064,
                R.drawable.final_0065,
                R.drawable.final_0066,
                R.drawable.final_0067,
                R.drawable.final_0068,
                R.drawable.final_0069,
                R.drawable.final_0070,
                R.drawable.final_0071,
                R.drawable.final_0072,
                R.drawable.final_0073,
                R.drawable.final_0074,
                R.drawable.final_0075,
                R.drawable.final_0076,
                R.drawable.final_0077,
                R.drawable.final_0078,
                R.drawable.final_0079,
                R.drawable.final_0080,
                R.drawable.final_0081,
                R.drawable.final_0082,
                R.drawable.final_0083,
                R.drawable.final_0084,
                R.drawable.final_0085,
                R.drawable.final_0086,
                R.drawable.final_0087,
                R.drawable.final_0088,
                R.drawable.final_0089,
                R.drawable.final_0090,
                R.drawable.final_0091,
                R.drawable.final_0092,
                R.drawable.final_0093,
                R.drawable.final_0094,
                R.drawable.final_0095,
                R.drawable.final_0096,
                R.drawable.final_0097,
                R.drawable.final_0098,
                R.drawable.final_0099,
                R.drawable.final_0100,
                R.drawable.final_0101,
                R.drawable.final_0102,
                R.drawable.final_0103,
                R.drawable.final_0104,
                R.drawable.final_0105,
                R.drawable.final_0106,
                R.drawable.final_0107,
                R.drawable.final_0108,
                R.drawable.final_0109,
                R.drawable.final_0110,
                R.drawable.final_0111,
                R.drawable.final_0112,
                R.drawable.final_0113,
                R.drawable.final_0114,
                R.drawable.final_0115,
                R.drawable.final_0116,
                R.drawable.final_0117,
                R.drawable.final_0118,
                R.drawable.final_0119,
                R.drawable.final_0120
        };

        private Bitmap mainBitmap;
        private BitmapFactory.Options mBitmapOptions;
        private int currentFrameIndex = 0;

        WallpaperSerEngine() {
            diwaliImg = new Runnable() {
                public void run() {
                    drawFrame();
                }
            };
            initMainBitmap(getResources(), pirates[0]);
        }

        private void initMainBitmap(Resources res,int resId){
            mBitmapOptions = new BitmapFactory.Options();
            mBitmapOptions.inJustDecodeBounds = true;
            mBitmapOptions.inMutable = true;
            BitmapFactory.decodeResource(res, resId,mBitmapOptions);

            mainBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth,mBitmapOptions.outHeight,Bitmap.Config.ARGB_8888);
            mBitmapOptions.inJustDecodeBounds = false;
            mBitmapOptions.inBitmap = mainBitmap;//will cause the bitmap to be reused.
            mBitmapOptions.inSampleSize = 1;
        }

        public boolean setToFrame(int frameIndex){
            if(pirates != null && frameIndex >= 0 && frameIndex< pirates.length){
                currentFrameIndex = frameIndex;
                mainBitmap = BitmapFactory.decodeResource(getResources(), pirates[currentFrameIndex], mBitmapOptions);
                return true;
            }
            else return false;
        }


        @Override
        public void onCreate(SurfaceHolder holder){
            super.onCreate(holder);
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacks(diwaliImg);
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            mVisible = visible;
            if (visible) {
                drawFrame();
            } else {
                mHandler.removeCallbacks(diwaliImg);
            }
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            super.onSurfaceChanged(holder, format, width, height);
            drawFrame();
            mScaleX = width / (1f * icon.getWidth());
            mScaleY = height / (1f * icon.getHeight());
        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            mVisible = false;
            mHandler.removeCallbacks(diwaliImg);
        }


        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, float xStep,float yStep, int xPixels, int yPixels) {
            drawFrame();
        }

        @Override
        public void onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
        }

        private void drawFrame() {
            final SurfaceHolder holder = getSurfaceHolder();
            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {
                    drawPirate(c);
                }
            } finally {
                if (c != null)
                    holder.unlockCanvasAndPost(c);
            }
            mHandler.removeCallbacks(diwaliImg);
            if (mVisible) {
                mHandler.postDelayed(diwaliImg, 1000 / 24);
            }
        }

        private void drawPirate(Canvas c) {
            setToFrame(i);
            i++;
            if (i == 120) {
                i = 0;
            }
            Matrix matrix = new Matrix();
            c.scale(mScaleX, mScaleY);
            c.drawBitmap(mainBitmap, matrix, null);
        }
    }
}

最佳答案

对BitmapFactory.decodeResource(getResources(),pirates [i])的调用;创建一个新的位图。
我假设您的图像都具有相同的大小,因此您可以回收一个位图,而不是在每次图像更改时都创建一个新的位图。这将大大提高您的FPS。

回收位图:

private Bitmap mainBitmap;
private BitmapFactory.Options mBitmapOptions;
private void initMainBitmap(Resources res,int resId){
    mBitmapOptions = new BitmapFactory.Options();
    mBitmapOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId,mBitmapOptions);

    mainBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth,mBitmapOptions.outHeight,Bitmap.Config.ARGB_8888);
    mBitmapOptions.inJustDecodeBounds = false;
    mBitmapOptions.inBitmap = mainBitmap;//will cause the bitmap to be reused.
    mBitmapOptions.inSampleSize = 1;
}

private int currentFrameIndex = 0;
public boolean setToFrame(int frameIndex){
    if(pirates != null && frameIndex >= 0 && frameIndex< pirates.length){
        currentFrameIndex = frameIndex;
        mainBitmap = BitmapFactory.decodeResource(mResources, pirates[currentFrameIndex],mBitmapOptions);
        return true;
    }
    else return false;
}


使用此代码:

从引擎构造函数调用initMainBitmap函数:

WallpaperSerEngine() {
    diwaliImg = new Runnable() {
        public void run() {
            drawFrame();
        }
    };
    initMainBitmap(getResources(),pirates[0]);
}


您的drawPirate应该更改为:

private void drawPirate(Canvas c) {
        setToFrame(i);
        i++;
        if (i == 120) {
            i = 0;
        }
        Matrix matrix = new Matrix();
        c.scale(mScaleX, mScaleY);
        c.drawBitmap(mainBitmap, matrix, null);
}

10-07 19:19
查看更多