// ////////////////////////////////////////////////////////////////////////////
// // Drawing Thread Inner Class
// //////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
class DrawThread extends Thread {
boolean bExit;
SurfaceHolder holder;
DrawThread(SurfaceHolder Holder) {
holder = Holder;
bExit = false;
}
@Override
public void run() {
// Log.d("FLOW", "Thread, run");
while (!Thread.currentThread().isInterrupted()) {
Canvas c = null;
try {
c = holder.lockCanvas(null);
synchronized (holder) {
doDraw(c);
}
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
}
}
private void doDraw(final Canvas cv) throws NullPointerException {
long posX = 0, posY = 0;
byte flag;
final Paint paint = new Paint();
paint.setAntiAlias(true);
cv.drawColor(Color.TRANSPARENT, Mode.CLEAR);
// draw if current positions are updated
for( int i=0 ; i<9 ; i++ ){
if( drawTable[i].iIndex != -1 ){
if( drawTable[i].bShown ){
posX = (long)(0.01 * drawTable[i].dCurProg * (Center.x-drawTable[i].Origin.x)) + drawTable[i].Origin.x;
// Log.d("FLOW", "[doDraw] i="+i+" prog:" + drawTable[i].dCurProg +
// "Center.x:" + Center.x + "Origin.x:" + drawTable[i].Origin.x +"posX:" + posX );
posY = (long)(0.01 * drawTable[i].dCurProg * (Center.y-drawTable[i].Origin.y)) + drawTable[i].Origin.y;
if(!(drawTable[i].iIndex==0 || drawTable[i].iIndex==5)) {
cv.drawBitmap(padTable[drawTable[i].iIndex].Icon, posX, posY, null);
}
}
}
}
// update current positions in animation
for( int i=0 ; i<9 ; i++ ){
flag = drawTable[i].InAnimation;
if( (flag & 0x01) == 0x01 ){ // Arriving (0x01)
if( drawTable[i].dCurProg < 100.0 ){
drawTable[i].dCurProg = Math.max( drawTable[i].dCurProg + dArrivingSpeed, 100.0 );
Log.d("FLOW", "[doDraw] InArriving, i=" + i + ", dCurProg:" + drawTable[i].dCurProg + " InAni:" + drawTable[i].InAnimation );
} else {
Log.d("FLOW", "[doDraw] before Pangali, i=" + i + ", dCurProg:" + drawTable[i].dCurProg + " InAni:" + drawTable[i].InAnimation );
drawTable[i].InAnimation = (byte)(drawTable[i].InAnimation & 0xFE);
setKoreanNextDrawingTable(i); //Pangali('c')
Log.d("FLOW", "[doDraw] Pangali, i=" + i + ", dCurProg:" + drawTable[i].dCurProg + " InAni:" + drawTable[i].InAnimation );
}
} else if ( (flag & 0x02) == 0x02 ){ // Breaking 0x02
if( drawTable[i].dCurProg > 0.0 ){
drawTable[i].dCurProg = Math.min( drawTable[i].dCurProg - dBreakingSpeed, 0.0 );
Log.d("FLOW", "[doDraw] InBreaking i=" + i + ", dCurProg:" + drawTable[i].dCurProg + " InAni:" + drawTable[i].InAnimation );
} else {
drawTable[i].InAnimation = (byte)(drawTable[i].InAnimation & 0xFD);
}
} else if ( (flag & 0x04) == 0x04 ){ // Canceling 0x04
if( drawTable[i].dCurProg > 0.0 ){
drawTable[i].dCurProg = Math.min( drawTable[i].dCurProg - dCancelingSpeed, 0.0 );
Log.d("FLOW", "[doDraw] InBreaking i=" + i + ", dCurProg:" + drawTable[i].dCurProg + " InAni:" + drawTable[i].InAnimation );
} else {
drawTable[i].InAnimation = (byte)(drawTable[i].InAnimation & 0xFB);
}
}
else if ( flag != 0x00 ){
Log.d("FLOW", "flag:" + flag );
}
}
}
}
메인 액티비티에서 서피스 뷰를 상속한 클래스를 불러와 손가락 닿는 대로 그림을 옮겨 그리는 프로그램을 만들고 있습니다.
위 코드는 서피스 뷰 내부의 쓰레드로, 메인 쓰레드와 함께 돌며 좌표가 갱신되면 계속 다시 그림을 그려줍니다.
그런데 18번 줄 cv.drawBitmap(padTable[drawTable[i].iIndex].Icon, posX, posY, null); 이부분에서 종종
09-26 14:05:47.387: E/AndroidRuntime(21758): FATAL EXCEPTION: Thread-673
09-26 14:05:47.387: E/AndroidRuntime(21758): java.lang.ArrayIndexOutOfBoundsException: length=100; index=-1
09-26 14:05:47.387: E/AndroidRuntime(21758): at edu.esrc.crossK.AnEventMove$DrawThread.doDraw(AnEventMove.java:849)
09-26 14:05:47.387: E/AndroidRuntime(21758): at edu.esrc.crossK.AnEventMove$DrawThread.run(AnEventMove.java:818)
또는
09-26 14:14:25.145: E/AndroidRuntime(22166): FATAL EXCEPTION: Thread-679
09-26 14:14:25.145: E/AndroidRuntime(22166): java.lang.ArrayIndexOutOfBoundsException: length=100; index=-1
09-26 14:14:25.145: E/AndroidRuntime(22166): at edu.esrc.crossK.AnEventMove.setKoreanNextDrawingTable(AnEventMove.java:415)
09-26 14:14:25.145: E/AndroidRuntime(22166): at edu.esrc.crossK.AnEventMove$DrawThread.doDraw(AnEventMove.java:872)
09-26 14:14:25.145: E/AndroidRuntime(22166): at edu.esrc.crossK.AnEventMove$DrawThread.run(AnEventMove.java:818)
라고 이셉션이 뜹니다.
매번 뜨는 것은 아니고 어떤 때는 잘 동작하다가 어떤 때는 줄창 뜨네요...
뭐가 문제인지 도저히 모르겠습니다.ㅠㅠ
padTable의 length가 100인데 -1이 계속 들어간대서 padTable의 인덱스를 넣어줄때마다 로그를 찍어봐도 -1이 들어가는 건 없네요.
이셉션 발생 후에도 로그에는 -1이 아닌 정상 숫자가 들어가 있습니다...
아래는 간혹 같이 이셉션 부분에 걸리는 korean Next Drawing Table 함수입니다.
public void setKoreanNextDrawingTable( int dir ){
// not synchronized since it is called only in doDraw()
int n = drawTable[dir].iIndex;
for (int i=0 ; i<5 ; i++ ){
drawTable[i].bShown = false;
drawTable[i].InAnimation = 0;
drawTable[i].dCurProg = 0.0;
drawTable[i].iIndex = -1; // make it empty first
}
for (int i=0 ; i<padTable[n].iNumChild ; i++ ){
if(n>0 && padTable[n].Children[i]>0) {
int m = padTable[n].Children[i];
drawTable[padTable[m].iDir].iIndex = m;
drawTable[padTable[m].iDir].bShown= true;
drawTable[padTable[m].iDir].dCurProg= 80.0;
drawTable[padTable[m].iDir].InAnimation = 0x02;
}
}
}
로그상으론 역시 padTable의 인덱스로 -1이 들어가는 부분은 없습니다.
제가 뭔가를 간과하고 있는지, 아니면 혹시 drawBitmap 함수 자체에서 규정(?)해놓은 게 있는지 궁금합니다.




padTable이나 drawTable를 다른 쓰레드에서 사용하지 않나요?
동기화 문제인 것 같습니다.