就我而言,我为 Google Maps v2 (Android)编写课程,以组织移动/缩放操作的队列。如果您知道在第一个动画仍在运行时另一个动画已启动,则取消动画操作。
为了避免这个问题我写了课。它工作但我想知道它是线程安全吗?也许我错过了什么?提前谢谢。
public class MapDecoratorQueue {
private List<MapDecorator> queue = new Vector<MapDecorator>();
private boolean isRunning = false;
public synchronized void add(MapDecorator md) {
if (isRunning) {
queue.add(md);
} else {
queue.clear();
queue.add(md);
next(0);
isRunning = true;
}
}
private void next(final int pos) {
if (queue.isEmpty()) {
isRunning = false;
} else {
MapDecorator decorator = queue.get(pos);
L.log(MapDecoratorQueue.class.getSimpleName(), "isMove: "
+ decorator.isMove() + " isZoom: " + decorator.isZoom());
if (decorator.isMove()) {
decorator.map.moveCamera(decorator.move);
}
if (decorator.isZoom()) {
decorator.map.animateCamera(decorator.zoom,
decorator.zoomDuration, new CancelableCallback() {
@Override
public void onFinish() {
queue.remove(pos);
next(pos);
}
@Override
public void onCancel() {
L.log(MapDecoratorQueue.class.getSimpleName(),
"cancelled");
queue.clear();
isRunning = false;
}
});
}
}
}
public static class MapDecorator {
private GoogleMap map = null;
private CameraUpdate move = null;
private CameraUpdate zoom = null;
private int zoomDuration = 0;
/**
* Для передвижения камеры и анимации
*
* @param move
* @param zoom
* @param zoomDuration
*/
public MapDecorator(GoogleMap map, CameraUpdate move,
CameraUpdate zoom, int zoomDuration) {
this.map = map;
this.move = move;
this.zoom = zoom;
this.zoomDuration = zoomDuration;
}
/**
* Только для передвижения камеры
*
* @param move
*/
public MapDecorator(GoogleMap map, CameraUpdate move) {
this(map, move, null, 0);
}
/**
* Только для зума камеры
*
* @param zoom
* @param zoomDuration
*/
public MapDecorator(GoogleMap map, CameraUpdate zoom, int zoomDuration) {
this(map, null, zoom, zoomDuration);
}
public boolean isMove() {
return map != null && move != null;
}
public boolean isZoom() {
return map != null & zoom != null && zoomDuration >= 0;
}
public CameraUpdate getMove() {
return move;
}
public CameraUpdate getZoom() {
return zoom;
}
public int getZoomDuration() {
return zoomDuration;
}
}
}
答案 0 :(得分:1)
列表(cas中的Vector)是线程安全的,但是使用的运行方式不是。当线程尝试使用下一个方法获取元素时,当另一个尝试使用add添加一个元素时,您可以有一个竞争条件。如果第一个线程就在将isRunning设置为false之前,第二个线程在此时检查它就会出现问题。
将synchronized添加到next方法将解决问题。
答案 1 :(得分:1)
如果在下面的行中,可以异步使用CancelableCallback,那么当您将对下一个(pos)方法的访问权限泄露给其他线程时就会遇到麻烦,在这种情况下,MapDecoratorQueue不是ThreadSafe。
decorator.map.animateCamera(decorator.zoom,decorator.zoomDuration, new CancelableCallback(pos));
无论如何,根据Brian Goetz :),线程安全不应该依赖于客户端实现(在这种情况下是animatecamera)所以你的类不是线程安全的。为了使线程安全,你可以使下一步同步,如果你这样做,你不需要向量。 ArrayList可以正常工作。