baseContext, applicationContext, 그리고 this@MainActivity
왜 이 글을 적게 되었는가..
팝업에서 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