본문 바로가기

Android/기타

[Android] View가 NullPointerException을 내는 경우

반응형

View가 NullPointerException을 내거나 혹은 다이얼로그를 보여주려고 할 때 발생하는 android.view.WindowManager$BadTokenException 등이 이 글에 해당한다.

 

초보자들의 경우 많이 접하는 에러 중에 하나가 아닐까 싶다. 심지어 Firebase Crashlytics에서는 android.view.WindowManager$BadTokenException인 경우 수정하는 방법까지 알려주니 말이다.

 

분명 코드상으로는 에러가 날 수 없는 상황임에도 불구하고 에러가 나오니 개발자 입장에서는 답답할 수 밖에 없다. Thread 문제와도 전혀 상관이 없다. 그럼 왜 View가 null이 되는 경우가 생기는 것일까? 이는 안드로이드의 기본인 Activity, Fragment의 LifeCycle과 관련이 있다.

 

Activity의 오버라이드가 가능한 함수 중에 onDestroy와 Fragment의 onDetach가 있는데 이는 Activity, Fragment가 종료되기 직전에 불리는 메소드이다. 그럼 Activity는 여기서 무슨 작업을 할까? 당연히 Activity에 할당된 메모리를 GC가 가비지 콜렉션할 수 있도록 자신이 가지고 있는 멤버변수, 뷰 등 참조 가진 모든 것들을 다 해제할 것이다. 그리고 나서 GC가 가비지 콜렉션하기를 기다린다.

 

그럼 이것이 왜 문제가 될까? 문제는 네트워크 콜은 비동기로 동작하기 때문이다. 비동기로 동작하는 네트워크 콜에 대한 응답 시점은 Activity, Fragment의 LifeCycle과는 상관이 없다. 만약 응답을 받았을 때 Activity 혹은 Fragment가 종료된 상황이라면 View를 조작하거나 혹은 다이얼로그를 띄울려고 할 때 지금 이 글의 주제에 있는 에러들을 보게 되는 것이다.

 

그럼 응답을 받았을 때 어떻게 대응을 해야할까?

Activity의 경우 다음처럼 처리를 하면 된다.

// @TODO : UI와 관련이 없는 코드

if (isFinishing()) {
	return;
}

// @TODO : UI 갱신 혹은 다이얼로그 띄우는 코드

Fragment의 경우는 다음과 같이 처리한다.

// @TODO : UI와 관련이 없는 코드

if (!isAdded()) {
	return;
}

// @TODO : UI 갱신 혹은 다이얼로그 띄우는 코드

 

반응형