5

我的自定义视图的 OnDraw 函数被无限调用并且正在循环!可能的原因是什么?

这是我的自定义视图:-

public class Balls extends View{

    private static final String TAG = "BallsView";

    private int mMode = READY;
    public static final int PAUSE = 0;
    public static final int READY = 1;
    public static final int RUNNING = 2;
    public static final int LOSE = 3;

    private final Paint mPaint = new Paint();
    private double mUx = 0.1;
    private double  mUy = 2;
    private double mVy;
    private double mVx;
    private double mSx;
    private double mSy;
    private double mRange;
    private float mX1;
    private float mY1;
    private int mX2;
    private int mY2;
    private int mDx;
    private int mDy;
    Time t;
    float mAngle;
    private final double mGravity = -9.8;

    private long mLastTime;

    private double mT;

    private Canvas mCanvas = null;



    public Balls(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
        setFocusable(true);
        setWillNotDraw(false);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 
        mPaint.setStrokeWidth(10); 
        mPaint.setAntiAlias(true); 
        mPaint.setStrokeCap(Cap.ROUND); 
        //mPaint.setColor(0xff00ffff);
        mPaint.setARGB(255, 0, 255, 0);

        mLastTime = System.currentTimeMillis();


    }
    public Balls(Context context, AttributeSet attrs) {
        super(context, attrs);
         setFocusable(true);
         setWillNotDraw(false);
          mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 
          mPaint.setStrokeWidth(10); 
          mPaint.setAntiAlias(true); 
          mPaint.setStrokeCap(Cap.ROUND); 
          mPaint.setColor(0xff00ffff);

    }

     @Override
    public void onDraw(Canvas canvas) {
         Log.w(this.getClass().getName(),"onDraw of Balls called");
      super.onDraw(canvas);
      mCanvas = canvas;

      if(mCanvas!= null)
          Log.w(this.getClass().getName(),"Canvas is not null");

    }

这种观点在另一项活动中被夸大如下:-

mBalls = (Balls) findViewById(R.id.balls);

此视图放置在相对视图内的 xml 文件中,相对视图是水平滚动视图的子视图。

4

4 回答 4

5

这里没有无限循环。正在发生的事情是操作系统正在尽可能快地重绘您的活动。当您的活动被重绘时,它会重绘其所有子视图。由于您的代码计算量很少,从我在这里可以看到,它运行得非常快,并且可能以 >30 FPS 的速率重绘。您的日志消息使它看起来好像没有无限循环。实际上,您的onDraw方法中甚至没有循环。

为了说明发生了什么,试试这个。将受保护的成员添加drawCount到您的Balls类并将其设置为 0:

protect int drawCount = 0;

然后附加drawCountonDraw日志消息的末尾

 public void onDraw(Canvas canvas){
       drawCount++;
       Log.w(this.getClass().getName(),"onDraw of Balls called. Total draws:" + Integer.toString(drawCount));
  ...
  }

您应该看到的是每条日志消息都会显示不同的 drawCount。

如果您想花哨并计算应用程序的帧速率,您可以测量自第一次绘制以来的时间,然后除以经过drawCount的时间,这将为您估算活动帧速率。

于 2011-10-12T14:16:49.917 回答
5

onDraw(Canvas)像在无限循环中那样经常调用,是不正常的。invalidate如果没有跟随或布局更改,通常应该调用 1 到 3 次。无限循环的原因可能是:
1,你打电话invalidatepostInvalidate某个地方。
2、父级或兄弟级布局一直在变化。
3、使用View.LAYER_TYPE_SOFTWARE,es。setLayerType(View.LAYER_TYPE_SOFTWARE, null)。
值得注意的是 LAYER_TYPE_SOFTWARE 将导致onDraw()被调用,就像在循环中一样。

于 2017-06-22T11:05:41.790 回答
3

onDraw() 在无效时调用。当视图或其父视图需要更改并且必须更改其状态时,将调用 Invalidate() get。

于 2011-10-12T03:39:27.040 回答
0

对我来说,发生这种情况是因为我有一些代码正在修改内部覆盖的 UI DispatchDraw..

于 2018-11-07T12:10:23.750 回答