我注意到我的应用程序最近崩溃了很多,经过调试后我发现当我迭代哈希映射时,有些会随机崩溃。
我像那样迭代他们:
for (Map.Entry<Point, Particle> entry : spawned.entrySet()) {
entry.getValue().Draw(canvas);
}
导致:
之后我尝试使用迭代器迭代它们:
Iterator<Map.Entry<Point, Particle>> entries = spawned.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Point, Particle> entry = entries.next();
entry.getValue().Draw(canvas);
}
但是这导致了:
这里面是粒子类,如果有人怀疑它必须对它做一些事情:
public class Particle {
Bitmap bit;
int alpha = 0;
boolean appeared = false;
boolean dissapiread = false;
int time = 1;
PointF position;
Handler handler;
int counter = 0;
PointF newpose;
float newsize=0;
int timer2=0;
public Particle(Bitmap b, PointF p, int time) {
int rand=(randInt(-b.getWidth()/2, b.getWidth()));
this.bit = Bitmap.createScaledBitmap(b, b.getWidth()+rand,b.getHeight()+rand,false);
this.position = p;
this.time = time;
newpose= new PointF();
newpose.x=p.x+randInt(-15000, 15000);
newpose.y=p.y+randInt(-15000,15000);
}
public void Draw(Canvas c) {
update();
Paint paintAlpha = new Paint();
paintAlpha.setAlpha(alpha);
c.drawBitmap(bit, position.x, position.y, paintAlpha);
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
private void update() {
if(position.x<newpose.x){
position.x+=0.10f;
}
if(position.x>newpose.x){
position.x-=0.10f;
}
if(position.y<newpose.y){
position.y+=0.10f;
}
if(position.y>newpose.y){
position.y-=0.10f;
}
if(dissapiread==false){
if(timer2==0){
newsize+=0.10;
try {
bit=Bitmap.createScaledBitmap(bit, bit.getWidth()-(int)newsize,bit.getHeight()-(int)newsize,false);
} catch (Exception e) {
// TODO: handle exception
}
timer2=5;
}
else
timer2--;
}
if (appeared == false) {
if (alpha <=240) {
alpha =alpha+10;
}
else {
if(counter==0){
counter=time;
}
if(counter==1){
appeared=true;
}
else
counter--;
}
} else {
if (dissapiread == false) {
if (alpha != 0) {
alpha=alpha-10;
}
else
dissapiread = true;
}
}
}
}
请注意,我知道在我目前的代码中我不必使用散列图,我只是想了解它崩溃的原因,因为它也发生在其他地方。
编辑: 整个代码:
public class gameview extends SurfaceView {
private GameLoopThread gameLoopThread;
private SurfaceHolder holder;
Bitmap partic;
Particle pp;
Map<Point, Particle> spawned = new HashMap<Point, Particle>();
public gameview(Context c) {
super(c);
partic=BitmapFactory.decodeResource(getResources(),
R.drawable.particle_fire);
pp=new Particle(partic, new PointF(0,0), 100);
gameLoopThread = new GameLoopThread(this);
this.requestFocus();
this.setFocusableInTouchMode(true);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
@Override
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawColor(Color.BLACK);
pp.Draw(canvas);
Iterator<Map.Entry<Point, Particle>> entries = spawned.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Point, Particle> entry = entries.next();
entry.getValue().Draw(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = (float) (event.getX());
float y = (float) (event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
spawned.put(new Point((int)x,(int)y), new Particle(partic, new PointF(x,y), 100));
break;
}
return super.onTouchEvent(event);
}
private void newParticle(int x,int y){
spawned.put(new Point(0,0), new Particle(partic, new PointF(x,y), 100));
}
}
答案 0 :(得分:0)
您在Partice
方法中更新了Draw
。这导致你在循环中遇到ConcurrentModificationException
。
如果要避免这种异常,可以创建一个“粒子集合”的克隆,通过该克隆迭代并修改原始数据。但是,克隆对于您需要做的事情来说可能非常麻烦。
使用克隆我的意思是将HashMap的键复制到一个新的Set中并迭代该集合。在循环中,您可以通过迭代的键访问HashMap值。修改粒子应该没问题。请注意,如果更新更改了对象的HashValue,则需要小心。
修改强>
正如@fge指出的那样,使用CuncurrentHashMap也可以解决问题。