0

我正在制作自定义滑动控件。就像一个音量轮,所以一些值会根据旋转方向增加或减少。我对此有两个问题:

  1. 性能真的很低
  2. 垃圾收集器多次触发。

好吧,我确定我做错了什么,所以请给我一盏灯。

我正在使用 2.1 (eclaire) SDK 上的 Android 图形。

这是从我的活动中调用的视图代码:

public class DrawingView extends View {

private Paint p;
Bitmap bitmap;
Context mContext;
Canvas canvas;
private float sweepAngle;
private int _height;
private int _width;
private float lastAngle;
private int percent;

public DrawingView(Context context) {
    super(context);
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    this.set_Width(display.getWidth());
    this.set_Height(display.getHeight());
    this.setSweepAngle(10);
    mContext = context;
    p = new Paint();
    p.setAntiAlias(true);

}

protected int getAngleFromLocation(Point location){
    int finalAngle = (int) (Math.atan2(location.y - 200, location.x - 200) * (180 / Math.PI));
    return finalAngle;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(),Bitmap.Config.ARGB_8888);
    this.canvas = new Canvas(bitmap);
    RectF rectF = new RectF();
    rectF.set(20, 20, this.get_Widtt() - this.get_Widtt()/10, this.get_Widtt() - this.get_Widtt()/10);
    canvas.drawArc(rectF, 180, this.getSweepAngle(), true, p);
    //invalidate();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    double increment = 3.6;
    Point touchLocation = new Point();
    touchLocation.x = (int)event.getX();
    touchLocation.y = (int)event.getY();
    canvas.drawBitmap(bitmap = Bitmap.createBitmap(canvas.getWidth(),canvas.getHeight(),Bitmap.Config.ARGB_8888),event.getX(), event.getY(),null );
    switch (event.getAction())
    { 
        case MotionEvent.ACTION_DOWN: 
            lastAngle = this.getAngleFromLocation(touchLocation);
            System.out.println("ACTION_DOWN");
            break;

        case MotionEvent.ACTION_MOVE:
            System.out.println("ACTION_MOVE");
            int currentAngle = this.getAngleFromLocation(touchLocation);
            System.out.println("CURRENT ANGLE: " + currentAngle); 
            if (currentAngle > lastAngle || (currentAngle == 1 && lastAngle == 359)) {
                percent += increment;
            } else if (currentAngle < lastAngle) {
                percent -= increment;
            }
            if (percent > 360) {
                percent = 360;
            } else if (percent < 0) {
                percent = 0;
            }
            lastAngle = currentAngle;
             this.setSweepAngle(percent);
             //Write the label
             //int realPercent = percent*100/360;
            System.out.println("PERCENT: "+percent); 
            break;

        case MotionEvent.ACTION_UP:
            break;
    }
    return true;
}
}
4

2 回答 2

3

无需在每一帧上创建一个新的位图。事实上,你应该尽量避免在 onDraw() 中分配任何对象。

试试这个:

private RectF mRectF = new RectF();

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.BLACK);
    mRectF.set(20, 20, this.get_Widtt() - this.get_Widtt() / 10, this.get_Widtt() - this.get_Widtt() / 10);
    canvas.drawArc(rectF, 180, this.getSweepAngle(), true, p);
}

同时删除 onTouchEvent 中对 canvas.drawBitmap() 的调用。

于 2012-09-24T13:18:30.997 回答
0

很可能是位图/画布的创建花费了这么长时间并且触发了 GC 这么多。onDraw()您希望在特别是期间尽可能少地创建对象,而且onTouchEvent()也是如此。有什么理由不能将它移到一个单独的方法中,该方法被调用一次并在每帧重用相同的位图?看起来您传递给的值createBitmap()是静态的,所以它不应该是一个问题。

于 2012-09-24T13:19:14.663 回答