Android 从ArrayList中绘制路径';行不通
当我在屏幕上移动手指时,尝试绘制路径时,我的应用程序强制关闭。代码开始在路径中绘制一些线,但随后强制关闭。我做错了什么 MainActivity类中的OnTouchListener:Android 从ArrayList中绘制路径';行不通,android,Android,当我在屏幕上移动手指时,尝试绘制路径时,我的应用程序强制关闭。代码开始在路径中绘制一些线,但随后强制关闭。我做错了什么 MainActivity类中的OnTouchListener: @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: gameLoop.touchD
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
gameLoop.touchDownX = event.getX();
gameLoop.touchDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
Point point = new Point();
point.x = (int) event.getX();
point.y = (int) event.getY();
gameLoop.addPoints(point);
gameLoop.startDrawLine = true;
break;
case MotionEvent.ACTION_UP:
gameLoop.touchUpX = event.getX();
gameLoop.touchUpY = event.getY();
gameLoop.touchActionUp = true;
break;
}
return true;
}
GameLoop类中的draw方法:
// Method to draw objects
private void drawObjects(Canvas canvas) {
// Clear screen with black color
canvas.drawRGB(0, 0, 0);
// Draw line
if(startDrawLine) {
// Set properties to Paint object
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
// Draw path
path.moveTo(touchDownX, touchDownY);
for(Point point: points) {
path.lineTo(point.x, point.y);
canvas.drawPath(path, paint);
}
path.reset();
}
日志信息:
04-28 11:54:23.155: W/dalvikvm(2896): threadid=10: thread exiting with uncaught exception (group=0x40018578)
04-28 11:54:23.155: E/AndroidRuntime(2896): FATAL EXCEPTION: Thread-11
04-28 11:54:23.155: E/AndroidRuntime(2896): java.util.ConcurrentModificationException
04-28 11:54:23.155: E/AndroidRuntime(2896): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
04-28 11:54:23.155: E/AndroidRuntime(2896): at com.androidTest.mergemania.GameLoop.drawObjects(GameLoop.java:251)
04-28 11:54:23.155: E/AndroidRuntime(2896): at com.androidTest.mergemania.GameLoop.run(GameLoop.java:216)
04-28 11:54:23.155: E/AndroidRuntime(2896): at java.lang.Thread.run(Thread.java:1019)
这就是drawObjects中的所有代码吗?LogCat告诉我们您在迭代列表时正在修改列表。我希望您有这样一个代码,它会中断:
for(Point point: points) {
path.lineTo(point.x, point.y);
canvas.drawPath(path, paint);
points.remove(point); // this line added
}
编辑:
哦,您可能正在使用SurfaceView
并在单独的线程中绘制。在这种情况下,您需要将调用同步到点列表。可能使用CopyOnWriteArrayList
请阅读关于穿线的文章
Edit2:
类似的东西应该可以工作,但我真的不会在生产代码中使用它,因为它会阻塞线程。为了使线程高效地工作,您需要非常少量的代码(就执行时间而言)。(添加了4行,注释为添加了该行
)
这是:
// Method to draw objects
private void drawObjects(Canvas canvas) {
synchronized (this) { // this line added
// Clear screen with black color
canvas.drawRGB(0, 0, 0);
// Draw line
if(startDrawLine) {
// Set properties to Paint object
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
// Draw path
path.moveTo(touchDownX, touchDownY);
for(Point point: points) {
path.lineTo(point.x, point.y);
canvas.drawPath(path, paint);
}
path.reset();
}
} // this line added
您在哪里调用
drawObjects
?异常表示您正在同时修改来自多个线程的点集合。您需要同步对集合的访问,以便在另一个线程迭代其内容时,不能从一个线程进行任何修改。您可能需要试一试。我正在canvas=surfaceHolder.lockCanvas()之间通过run()方法调用drawObjects;和surfaceHolder.unlockCanvasAndPost(画布);我猜列表必须在我触摸手指并存储点的同时进行修改,同时迭代列表才能画出线!?有更好的方法吗?是的,我正在使用SurfaceView,但我应该同步什么?@3D Krativ如果你不做复杂的计算(而且看起来不像你做的那样)来绘制东西,我建议现在扩展视图
和onDraw
,而不是让事情复杂化。同步将不会有问题。但是如果你想坚持使用SurfaceView
-只需使用synchronize(…){}
block.Hmm包装所有对点的访问变量,这很难理解!我应该在上面的代码前面使用synchronize(..):if(startDrawLine){….?感谢添加的代码!现在它可以工作了,但它会大大降低画布上其他移动对象的速度!这可能是什么原因?我认为SurfaceView比View更好使用,为什么不将其用于生产?很难知道什么是好的,什么是坏的!我应该如何改进我的代码?
// Method to draw objects
private void drawObjects(Canvas canvas) {
synchronized (this) { // this line added
// Clear screen with black color
canvas.drawRGB(0, 0, 0);
// Draw line
if(startDrawLine) {
// Set properties to Paint object
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
// Draw path
path.moveTo(touchDownX, touchDownY);
for(Point point: points) {
path.lineTo(point.x, point.y);
canvas.drawPath(path, paint);
}
path.reset();
}
} // this line added