如何使Android应用程序(动画)更快/更顺畅?

时间:2013-02-27 18:27:53

标签: java android animation frame-rate smooth

我已经开始开发吉他应用程序了,并且陷入了图形方面。我的屏幕包含一个背景图像,您可以通过向上或向下滑动两个手指移动。我的背景图片,一个位图,在Android设备上以低fps移动。我正在寻找如何让它运行更顺畅。

代码详情: 我有3个类:一个主要活动,第二个用于图形,第三个用作启动画面(我没有包括最后一个,因为它与我的问题无关)。

MainActivity.java

package com.example.androidapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;


public class MainActivity extends Activity implements OnTouchListener{

    FretBoard ourView;
    float y1, y2, dy;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        ourView = new FretBoard(this);
        ourView.setOnTouchListener(this);
        setContentView(ourView);

    }

    //Method to be used in future
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        ourView.pause();
    }

    //Method to be used in future
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        ourView.resume();
    }



    @Override
    public boolean onTouch(View v, MotionEvent event){

        //For debugging
        if(event!= null) ourView.fingerCount = event.getPointerCount();

        switch(event.getAction()){

            case MotionEvent.ACTION_DOWN:

                //Save first y position when finger touches screen
                y1 = event.getY();

                break;


            case MotionEvent.ACTION_MOVE:

                if(event != null && event.getPointerCount() == 2){

                    //Save second y position when finger moves
                    y2 = event.getY();

                    //Total distance moved
                    dy = y2 - y1;
                    if((ourView.bgY + dy)<0) ourView.bgY += dy/2;

                    //For Debugging
                    System.out.println("Y1 : " + y1 + "     Y2 : " + y2                +   "   DY : " + dy);

                    //Redraw the Screen 
                    ourView.invalidate();

                    //Reset y1 
                    y1 = y2;
                }

                break;
        }
        return true;
    }

}

FretBoard.java

package com.example.androidapplication;

import java.io.InputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class FretBoard extends SurfaceView implements Runnable{

    //Background image variables
    Bitmap background;
    InputStream is = getResources().openRawResource(R.drawable.fret_board);

    //Debugger text variables
    Paint mPaint = new Paint();
    String string = "Fingers: ";
    int fingerCount = 0;

    //Position Variables
    int width, height;
    float bgY = 0, bgX = 0;

    //Holder variable
    SurfaceHolder ourHolder;

    //To be used in future
    Thread ourThread = null;
    Boolean isRunning = false;

    public FretBoard(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        ourHolder = getHolder();
        ourThread = new Thread(this);
        ourThread.start();

    }

    //To be used in the future
    public void pause(){
        isRunning = false;
        while(true){
            try {
                ourThread.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        }
        ourThread = null;
    }

    //To be used in the future
    public void resume(){
        isRunning = true;
        ourThread = new Thread(this);
        ourThread.start();
    }


    //Creates a InputStream to set width, then converts to bitmap to be
    //drawn as background on the canvas.
    public Bitmap bmScale(InputStream is){
       BitmapFactory.Options o = new BitmapFactory.Options();
       o.inSampleSize = 2;
       Bitmap bit = BitmapFactory.decodeStream(is, null, o);
       background = Bitmap.createScaledBitmap(bit, width, 2300, true);
       bit.recycle();
       return background;
    }


    //This is the draw method where I need help
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(isRunning){
            if(!ourHolder.getSurface().isValid()) continue;

            //Lock canvas to draw 
            Canvas canvas = ourHolder.lockCanvas();

            //Do Things Here:
            width = getWidth();
            height = getHeight();

            //Collision detection for the background
            if(bgY > 0 ) bgY = 0;

            //Draws the background
            bmScale(is);
            canvas.drawBitmap(background, bgX, bgY, null);

            //For debugging, displays the number of fingers on the screen
            canvas.drawText(string + fingerCount, 50, 50, mPaint);

            //Unlock canvas to show 
            ourHolder.unlockCanvasAndPost(canvas);
        }
    }   
}

2 个答案:

答案 0 :(得分:3)

您似乎在每个渲染过程中加载/读取和缩放位图。这非常低效。 (请参阅FretBoard.java中对bmScale(is);的调用)。

相反,只加载(并缩放你的)位图一次(当视图布局时),然后绘制已加载和缩放的位图。

此外,您似乎为SurfaceView使用了FretBoard。为什么?在您的代码示例中,您根本不使用OpenGL或视频/相机纹理。

答案 1 :(得分:0)

在循环中缩放(如此处的其他答案所述)绝对是您的主要问题。一旦你解决了这个问题,事情就会变得更加顺畅。你可能会发现一些小的口吃,因为你在循环中创建其他对象,即字符串。假设你一次在指板上永远不会有超过5个手指(好的,如果你正在敲击,理论上可能是10个)string只有5或10个可能的值(顺便说一下,这是一个令人困惑的名字) ,特别是在这种情况下)。最好先在循环之外创建这些,然后选择正确的参考。