简体   繁体   English

在画布,动态壁纸项目上旋转多个位图; 为什么每个额外的位图会使每个drawFrame()这么慢? (包括代码!)

[英]Rotating multiple bitmaps on a canvas, live wallpaper project; why does each additional bitmap slow down each drawFrame() so much? (code included!)

I am working on a live wallpaper (my first actually :)), and I seem to have a reached an impasse: 我正在制作动态壁纸(实际上是我的第一个:)),似乎陷入了僵局:

If you haven't guessed it by the variable names and the code, the live wallpaper in question is a clock. 如果您没有通过变量名和代码来猜中,那么所讨论的动态壁纸就是一个时钟。 Its components must follow a very strict degrees/time ratio (in total there will be over a dozen bitmaps rotating at different rates, in different directions (some following the same ratios/rules)). 它的组成部分必须遵循非常严格的度/时间比率(总共将有十几个位图以不同的速率沿不同的方向旋转(某些遵循相同的比率/规则))。

Anyways... As it stands, every additional bitmap that is added pretty much doubles the length of execution of drawFrame(). 无论如何...就目前而言,添加的每个其他位图几乎使drawFrame()的执行时间加倍。 If I was going to stop at 3 moving parts, it wouldn't be so bad, it looks OK as is; 如果我要在3个移动部件处停下来,那还不错,它看起来还不错。 but increase the amount of bitmaps by 9 (or even 2 or 3 more) and the frame rate becomes unacceptable. 但将位图的数量增加9个(甚至再增加2个或3个),则帧速率将变得不可接受。

I am not re-decoding bitmaps every turn as is recommended... 我并没有按照建议的那样每次都重新解码位图...

What should I do to remedy this situation? 我该怎么办才能纠正这种情况?

I was thinking of looking into openGL surface/engine, but i saw an exchange on SO where a user was handling over 100 bitmaps at once without problem ( Android drawBitmap Performance For Lots of Bitmaps? ), which got me hoping I could do the same. 我当时正在考虑研究openGL表面/引擎,但是我看到一个关于SO的交流,其中用户一次可以毫无问题地处理100多个位图( Android drawBitmap Performance For Bitbits的性能? ),这让我希望我能做同样的事情。

I also included an appropriate version of each image in the respective drawable -_dpi folders. 我还在相应的可绘制-_dpi文件夹中包括了每个图像的适当版本。 The images are not particularly large, file size is fairly small as there are very colors and lots of transparent portions (largest is = screen size, smallest = 90%widthscreen/50% height of screen -- so for xhdpi 720 1280 biggest and 565*562 smallest) 图像不是特别大,文件大小相当小,因为有很多颜色并且有很多透明部分(最大=屏幕尺寸,最小=屏幕宽度的90%/屏幕高度的50%-因此对于xhdpi 720 1280最大和565 *最小562)

So basically, according to my research, my code should be snappy... but it's not. 因此,基本上,根据我的研究,我的代码应该很活泼……但事实并非如此。 Clearly I am wrong :), please help me get it right! 显然我错了:),请帮助我正确设置!

Thank you very much. 非常感谢你。

void drawFrame()
    {
        timeSinceLastRun = AnimationUtils.currentAnimationTimeMillis() - timeAtLastRun;
        timeAtLastRun = AnimationUtils.currentAnimationTimeMillis();

        final SurfaceHolder holder = getSurfaceHolder();
        Canvas c = null;
        try
        {

            c = holder.lockCanvas();
            if (c != null)
            {
                c.save();
                c.drawColor(0xff000000);
                drawTouchPoint(c);
                if(isItPhase1)
                {
                    skipToPosition(c,0,0,false,1);
                    skipToPosition(c,1,1,false,2);
                    skipToPosition(c,2,2,true,3);
                }
                else
                {

                    animateGears(c,0,0,0,0);
                    animateGears(c,1,1,1,1);
                    animateGears(c,2,2,2,2);
                }

                c.restore();
            }
        }
        finally
        {
            if (c != null)
                holder.unlockCanvasAndPost(c);
        }

        mHandler.removeCallbacks(mDrawPattern);
        if (mVisible)
        {
            mHandler.postDelayed(mDrawPattern, 1000/25);
        }
    }

    private void skipToPosition(Canvas c, int xP, int yP, boolean lastTest, int timeBasis)
    {
        if(isItFirstRun)
        {
            gears[0] = BitmapFactory.decodeResource(getResources(), 
                    l.werner.mechanicalclocklivewallpaperversion0001.R.drawable.seconds_gear);

            gears[1] = BitmapFactory.decodeResource(getResources(), 
                    l.werner.mechanicalclocklivewallpaperversion0001.R.drawable.minutes_gear);

            gears[2] = BitmapFactory.decodeResource(getResources(), 
                    l.werner.mechanicalclocklivewallpaperversion0001.R.drawable.hours_gear);

            m[0] = new Matrix();
            m[1] = new Matrix();
            m[2] = new Matrix();
            m2[0] = new Matrix();
            m2[1] = new Matrix();
            m2[2] = new Matrix();

            x[0] = 0;
            x[1] = 0;
            x[2] = 0;
            y[0] = 0.006f;
            y[1] = 0.0001f;
            y[2] = (0.000001666666666666666666666666666666667f);
            timeSinceLastRun = 0;
            movementPerTurn = 0;
            isItFirstRun = !isItFirstRun;
        }
        Calendar cal = Calendar.getInstance();
        float second = cal.get(Calendar.SECOND);
        float minute = cal.get(Calendar.MINUTE);
        float hour = cal.get(Calendar.HOUR);
        if(timeBasis == 1)
            x[xP] = x[xP] + (360f*(second/60f));
        else if(timeBasis == 2)
            x[xP] = x[xP] + (360f*(minute/60f));
        else if(timeBasis == 3)
            x[xP] = x[xP] + (360f*(hour/12f));
        if(lastTest)
        {
            isItPhase1 = !isItPhase1;
        }
    }

    void animateGears(Canvas c, int xP, int yP, int g, int mP)
    {
        movementPerTurn = y[yP] * timeSinceLastRun;

        x[xP] = x[xP] + movementPerTurn;

        m[mP].setRotate(((float)x[xP]*1f), 0.5f*gears[g].getWidth(),0.5f*gears[g].getHeight());
        m2[mP].setTranslate(c.getWidth()/2f - 0.5f*gears[g].getWidth(),
                c.getHeight()/2f - 0.5f*gears[g].getHeight());
        m[mP].setConcat(m2[mP], m[mP]);

        c.drawBitmap(gears[g], m[mP] , null);
    }

Consider using separate thread for animation. 考虑使用单独的线程进行动画处理。 You may easily test this solution by using live wallpaper template I've posted on GitHub and see if it will make you a difference. 您可以使用我在GitHub上发布的动态壁纸模板轻松测试此解决方案,并查看它是否会对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM