我的自定义View的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文件中,相对视图是水平滚动视图的子视图。
答案 0 :(得分:5)
这里没有无限循环。发生的事情是操作系统正在尽快重新绘制您的活动。当您的活动重新绘制时,它会重绘其所有子视图。由于你的代码计算量很少,从我在这里看到的,它运行速度非常快,并且可能以大于30 FPS的速率重绘。您的日志消息使其看起来好像存在无限循环。事实上,onDraw
方法中甚至没有循环。
为了说明发生了什么,试试这个。将受保护的成员drawCount
添加到Balls
类并将其设置为0:
protect int drawCount = 0;
然后将drawCount
附加到onDraw
日志消息的末尾
public void onDraw(Canvas canvas){
drawCount++;
Log.w(this.getClass().getName(),"onDraw of Balls called. Total draws:" + Integer.toString(drawCount));
...
}
您应该看到的是每条日志消息都会显示不同的drawCount。
如果你想得到想象并计算你的应用程序的帧率,你可以测量自第一次抽奖以来的时间,然后将drawCount
除以已经过了多少时间,这将估计你的活动帧率
答案 1 :(得分:3)
onDraw()在invalidate处调用。当视图或其父级感觉需要更改并且必须更改其状态时,会调用Invalidate()。
答案 2 :(得分:2)
onDraw(Canvas)
经常被称为无限循环,这是不正常的。
通常,如果没有跟随invalidate
或布局更改,则应调用1到3次。
无限循环的原因可能是:
1,您在某处注明了invalidate
或postInvalidate
2,父母或兄弟姐妹的布局一直在变化
3,使用View.LAYER_TYPE_SOFTWARE,es。 setLayerType(View.LAYER_TYPE_SOFTWARE,null)。
值得注意的是,LAYER_TYPE_SOFTWARE将导致onDraw()
被调用,就像在循环中一样。
答案 3 :(得分:0)
之所以如此,是因为我有一些代码正在修改被覆盖的DispatchDraw
中的UI。