회사에서 개발 하다 문제가 발생해서 메일로 정리 했던것을 옮겼습니다.
개발간 activity를 종료할 때 계속 원하는 동작이 되지 않아서 답답해했는데요.
로그도 나오질 않고 해서 한 줄씩 디버깅했습니다.
원인은 activity 를 finish() 하는 부분에서 문제가 발생했습니다.
for (Activity activity : activityStack) {
if (activity == null) {
continue;
}
try {
activity.finish();
} catch (Exception e) {
DebugLogger.w(TAG, "When acitivity finish, exception.");
}
}
위의 코드에서 결국 ConcurrentModificationException 예외가 발생한 것으로나오네요.
이는 동기화 관련 문제로 데이터에 대해서 무결성이 입증되지 않을 때 문제가 발생된다고 합니다.
static으로 되어있는 activityStack을 for문을 돌면서 activity를 종료하다 보니
실제로 finish를 하게 되면 activityStack의 size도 1개 줄어 들게 됩니다.
처음 하나를 종료하고 나서 돌아와보니 데이터가 달라보여 처리를 못해주고 예외가 발생합니다.
즉, for문의 주체를 내부에서 제거 하는 행동은 좋지 않아 보입니다. 해야하는 경우도 있지만 위의 for문의 경우에는 위험하다는 결론입니다.
예전에 for문 쓸 때 위의 방식을 쓰기 보다는 기본적으로 쓰는 (int i = 0; I < size; i++) 형식을 선호하라고 들었었는데
그땐 왜 그래야 하는지 몰랐는데 저런 문제 때문이지 않을까 합니다.
해결방법으로 처음 생각 한 게 아래 방법
for (int i = 0; i < activityStack.size(); i) {
Activity activity = activityStack.get(i);
if (activity == null) {
continue;
}
try {
activity.finish();
} catch (Exception e) {
DebugLogger.w(TAG, "When acitivity finish, exception.");
}
}
for문을 (i=0;i<size;i) 형식으로 변경하고 size가 0이 될 때 까지 맨 처음 것을 가져와서 종료하는 방식입니다.
우선 맨 위에 것을 먼저 지우는 것도 이상해 보이고
그 닥 코드가 좋아 보이지 않아서 for문 말고 while문을 쓰기로 했습니다.
그래서 최종 수정된 게 아래 방법입니다.
while (activityStack.size() != 0) {
Activity activity = activityStack.get(getActivityStackSize() - 1);
if (activity == null) {
continue;
}
try {
activity.finish();
} catch (Exception e) {
DebugLogger.w(TAG, "When acitivity finish, exception.");
}
}
size가 0이 될 때 까지 마지막 올린 것부터 finish시키도록 했습니다.
정상적으로 모든 activity가 종료되네요.
결론은 for문에서 데이터 무결성을 위해서 for문의 주체인 내부를 remove하는 행동은 자제하자.
(int i=0; 비교문; i++) 형식의 for문을 되도록 사용하자 입니다.
'프로그래밍 > 안드로이드(Android)' 카테고리의 다른 글
[Android] Hex Opacity Values (Text Alpha 값 적용하기) (0) | 2015.08.27 |
---|---|
스크린 크기 값 구하기 (0) | 2013.12.12 |
[Android] Button 에 text 와 image 넣기 (xml , source) (0) | 2011.08.08 |
[Android] 화면 전환시 Activity 재생성 막기 (유용하게 사용하기) (0) | 2011.08.04 |
[Android] Shade효과 제거하기 (2) | 2010.12.02 |