안드로이드 애플리케이션을 개발하다 보면, Dialog 부류의 위젯을 많이 사용하게 된다. 그리고 이 위젯을 화면에 보여주고 완료하면 dismiss()를 호출해서 종료를 시킨다. 이 과정에서 java.lang.NullPointerException이 발생할 수 있다. 그리고 Activty가 Dialog보다 먼저 종료(finish() 호출되는 등)가 되는 상황에서는 아래의 예외를 발생시킨다. java.lang.IllegalArgumentException: View not attached to window manager.
아래는 API 문서의 구조로, Dialog 부류의 최상위는 DialogInterface라는 것을 알 수 있다.
위 구조에서 dismiss()를 가지고 있는 클래스는 Dialog로, 이 클래스의 구조도는 다음과 같다.
ProgressDialog를 사용하면서 dismiss()를 하는 일반적이 코드는 다음과 같다.
if(progressdialog != null && progressdialog.isShowing()) { progressdialog.dismiss(); }
이 코드는 대체로 동작을 하지만, 위에서 언급한 예외가 발생할 수 있기에, 위의 코드를 try ~ catch로 감싸는 코드를 종종 보게 된다. 그래서 dismiss()를 안전하고 verbose하지 않게 처리하기 위해서 아래와 같은 간단한 유틸 클래스를 사용하면 좋다.
public class DialogDismisser { public static void dismiss(DialogInterface d) { if(d == null) return; try { if(d instanceof AlertDialog) { if(((AlertDialog) d).isShowing()) ((AlertDialog)d).dismiss(); return; } if(d instanceof ProgressDialog) { if(((ProgressDialog) d).isShowing()) ((ProgressDialog)d).dismiss(); return; } if(d instanceof Dialog) { if(((Dialog) d).isShowing()) ((Dialog)d).dismiss(); return; } } catch(Exception e) { Log.e("dissmiss error", e); } } public static void dismiss(DialogInterface d1, DialogInterface d2) { dismiss(d1); dismiss(d2); } }
이 클래스를 사용해서 각종 Dialog의 dismiss()를 안전하게 종료시킬 수 있다. 혹시 cancel()을 사용한다면 이 클래스와 동일한 형태로 작성해서 사용하면 된다.