개발/Android

baseContext, applicationContext, 그리고 this@MainActivity

레란희 2023. 4. 23. 08:54

왜 이 글을 적게 되었는가..

 

팝업에서 ChipGroup을 사용할 일이 생겨서 열심히 코딩하고 실행까지 했는데

팝업을 열려고 할 때 갑자기 아래와 같은 오류가 생겼다.

 

The style on this component requires your app theme to be Theme.AppCompat (or a descendant).

 

오 앱 테마가 Theme.AppCompat을 상속받아야 하는가보다..

 

하지만 확인 결과 나는 application theme도 Material 테마였고, App Theme을 AppCompat을 상속받게 하였지만 문제는 나아지지 않았다.

 

그리고 30분째..나는 계속되는 구글링으로 지쳐가고있었고..

 

그러던 중 '혹시'나 해서

 

val dialog = ListDialog(baseContext)

val dialog = ListDialog(this@MainActivity)

로 바꿔봤더니..

 

잘 된다..?

 

도대체 이런 일은 왜 생긴 걸까...? 에서 시작한 오늘의 포스팅..

 

baseContext, applicationContext, 그리고 this@MainActivity는 무엇이 다른가!

 

지금 시작합니다!

 


1. this@MainActivity

가장 먼저, 가장 쉬운 this@MainActivity 먼저 살펴보겠다.

해석해보면 '이거@MainActivity'다.

그렇다!

이건 그냥 this 라는 예약어에다가.. 특별히 'MainActivity 말이야!' 라는 걸 붙여준 것이다.

메인액티비티 내에서 this만 써도 무관한 경우가 있지만, 경우에 따라 this가 꼭 MainActivity를 가리키지 않을 때가 있기 때문이다.

 

그렇다면 이제 this가 무엇인지를 확인해보자.

this는 해당 클래스 내에서 자기 자신의 객체를 반환할 때 쓰는 예약어라고 보면 된다.

 

따라서!

View.OnClickListener() {
	fun onClick(v: View) {
		Toast.makeText(this, "이건 오류남", Toast.LENGTH_SHORT).show()
    }
}

이 경우에는 this가 OnClickListener의 객체를 반환하기 때문에 오류가 난다.

this@MainActivity 처럼 사용하여야 한다.

 

결론 : this@MainActivity는 해당 액티비티의 객체를 반환하는 것이다. Activity는 Context를 상속받기 때문에 context를 대체해서 쓸 수 있는 거고..


2. baseContext

일단 이 녀석도 현재 액티비티 또는 서비스의 context를 반환한다.

'일반적으로' Toast나 Dialog같이 context가 필요한 개체를 만들 때 사용된다.

액티비티나 서비스와 연결되어있기 때문에 해당 액티비티나 서비스가 종료되면 함께 사라진다.

 

사실 이 녀석과 this@MainActivity의 차이를 잘 몰랐다.

그래서 위와 같은 사단이 났던 것..

 

this@MainActivity와 baseContext의 차이는...

현재 액티비티와 관련이 있다! 무적권 현재 액티비티를 넘겨줘야 한다! => this

일반적인 목적이다! 특정 액티비티와 연관이 있는 건 아니다! => baseContext

 

그리고 불러오는 곳도 다르다.

안드로이드 스튜디오에서 baseContext를 어디서 불러오냐 찾아보면

ContextWrapper 클래스에서 불러온다는 걸 알 수 있다.

 

this@MainActivity는 해당 Activity를 반환한다.

Activity는 ContextWrapper를 상속받은 ContextThemeWrapper를 상속받는다.

 

여기서 더 나아가서..

ContextWrapper.getBaseContext()는 open 키워드가 없는 것으로 볼 때 이는 오버라이드가 불가능하다는 것을 알 수 있다.

즉 getBaseContext()는 ContextWrapper단계에서 불러오지, 하위 Activity 등에서 불러오는 게 아니라는 것..

 

그렇기에 테마에 대한 값을 가지고 있지 않기에

AppCompat 테마가 필수인 ChipGroup은

'??님 이거 사용하려면 AppCompat 테마가 필요하다요!!'

하면서 에러를 내뿜었던 것이다.


3. applicationContext

이 녀석은 어플리케이션 단위의 context다. 

특정 액티비티에 국한되지 않은 Singleton Context라고 한다.

수명이 긴 개체에 넣어줘야할 때는 applicationContext를 사용하면 된다. 

예를 들어 글로벌 구성 설정, 애플리케이션 기본 설정 및 시스템 서비스와 같은 애플리케이션 수준 리소스 및 서비스에 대한 액세스를 제공하는 데 사용된다고 한다.

 

baseContext와 this@MainActivity가 특정 개체의 생명주기동안에만 유효하다고 한다면

applicationContext는 애플리케이션이 시작될 때 생성되고 애플리케이션의 전체 수명 주기 동안 활성 상태를 유지한다.

 

그렇기때문에 메모리 누수가 발생할 수 있으며 개발 시 이를 충분히 염두에 두어야 한다.

 


다 적고 났더니 뭔가 큰 걸 놓쳤다는 생각이 든다.

 

그렇다.

 

context가 뭔지에 대해서는 정리하지 않은 것이다.

 

context란? 직역하면 '문맥' 이런 뜻인데..

문맥이라는 건 '서로 이어져 있는 문장의 앞뒤 관계'를 말한다.

 

일반적으로 리소스에 액세스할 때, Activity를 시작할 때, 시스템 서비스에 액세스할 때, 팝업, 토스트 등의 개체를 만들 때 사용하는 클래스라고 보면 된다.

 

뭔가랑 뭔가를 이어줄 때 필요한 녀석이구나 정도로 이해하고 넘어가면 될 것 같다.

 

 

 


참고 :

 

chatGPT

https://mrgamza.tistory.com/197