어플리케이션 환경에 관한 글로벌 정보를 접근하기 위한 인터페이스. Abstract 클래스이며 실재 구현은 안드로이드 시스템에 의해 제공된다. Context 를 통해, 어플리케이션에 특화된 리소스나 클래스에 접근할 수 있을 뿐만 아니라, 추가적으로, 어플리케이션 레벨의 작업 - Activity 실행, Intent 브로드캐스팅, Intent 수신 등, 을 수행하기 위한 API 를 호출 할 수도 있다.
컨텍스트의 종류에는 2가지가 있다.
Application Context
실행 중인 안드로이드 어플리케이션의 Singleton Instance이다.
Activity/Service Context
Activity와 Service는 보인 그자체가 Context이다. Activity와 Service 모두 ContextWrapper를 상속 받는다. Activity Context인 경우 자신의 뷰 컴포넌트를 관리하기 위해 Application Context가 아닌, 자신의 Activity Context에 접근해야 한다. "this" 키워드를 이용해서 가능하다.
✅Context?
- Context는 애플리케이션 환경에 대한 글로벌 정보를 갖는 인터페이스(여기서의 인터페이스는 연결되는 부분.문법interface아님)
- 이름 그대로 해석한다면 애플리케이션(객체)의 현재 상태의 맥락(context)를 의미.
- 컨텍스트는 새로 생성된 객체가 지금 어떤 일이 일어나고 있는지 알 수 있도록 하기 때문에 액티비티와 애플리케이션에 대한 정보를 얻기 위해서는 컨텍스트를 사용
- 또한, 컨텍스트(Context)는 시스템의 핸들과도 같음. 리소스. 데이터베이스, preferences 등에 대한 접근을 제공.
- 액티비티는 애플리케이션이 현재 실행중인 환경에 대한 핸들과도 같음. 액티비티 객체는 컨텍스트 객체를 상속받음.
- 액티비티는 애플리케이션의 특정 리소스와 클래스, 그리고 애플리케이션 환경에 대한 정보에 대해 접근할 수 있게 해줌
- Context는 Android 시스템에서 구현체를 제공하는 추상 클래스로, 애플리케이션 별 리소스 및 클래스 접근에 사용되며, 액티비티 실행, 브로드캐스트, 인탠트 수신 등과 같은 애플리케이션 수준 작업에 사용됨.
✅Context의 종류
- Application Context
- Activity Context
Application Context
- 애플리케이션 컨택스트는 싱글턴 인스턴스이며, 액티비티에서
getApplicationContext()
를 통해 접근할 수 있음(Context타입).
- 이 컨택스트는 애플리케이션 라이프사이클에 묶여있으며, 현재 컨택스트가 종료된 이후에도 컨택스트가 필요한 작업이나 액티비티 스코프를 벗어난 컨택스트를 전달할 때에 적합.
- ex.애플리케이션에 싱글턴 오브젝트를 생성하고, 해당 오브젝트가 컨택스트가 필요하다면 항상 애플리케이션 컨텍스트를 전달하세요. 만약 액티비티 컨택스트를 전달한다면, 해당 오브젝트가 액티비티를 항상 참조하므로, 액티비티가 화면에 표시되지 않는 순간에도 가비지 콜렉션이 진행되지 않아 메모리 누수가 발생합니다.
- 애플리케이션 전체에서 사용할 라이브러리를 특정 액티비티에서 초기화한다면 어떤 Context를 전달해야 할까요? 당연히 Application Context입니다. getApplicationContext()는 딱 위와 같은 경우에만 사용하여야 합니다. 그 어떤 컨텍스트(Context)보다 오래 유지되는 컨텍스트(Context)가 필요할때에만 getApplicationContext()를 사용하세요.
Activity Context
- Activity는 최종적으로 Context를 상속받고 있음
- Activity를 사용하다보면 Context를 인자로 받는 것들을 많이 사용하게되는 이유
- Activity Context는 activity 내에서 유효한 컨택스트.
- Activity Context는 액티비티 라이프사이클과 연결되어 있음.
- 액티비티의 범위 내에서 컨텍스트를 전달하거나, 라이프사이클이 현재의 컨텍스트에 붙은 컨텍스트가 필요할 때 액티비티 컨텍스트를 사용
- Activity Context는 액티비티와 함께 소멸해야 하는 경우에 사용.
- ex.액티비티와 라이프사이클이 같은 오브젝트를 생성해야 할 때 액티비티 컨택스트를 사용할 수 있습니다.
- Application Context는 MyApplication, MainActivity1, MainActivity2 모두에서 사용할 수 있습니다.
- MainActivity1의 Context는 MainActivity1에서만 사용할 수 있습니다.
- MainActivity2의 Context는 MainActivity2에서만 사용할 수 있습니다.
✅ContentProvider의 getContext()
- 추상 클래스
ContentProvider
를 상속한 클래스에서 getContext()
메소드를 통해 불러올 수 있는 컨택스트는 애플리케이션 컨택스트임
✅언제, 어떤 Context를 사용해야 할까?
-
class MyApplication과 class MyDB 싱글턴이 있다고 가정해봅시다. 그리고 MyDB가 context가 필요한 상황이라면, 어떤 context가 필요할까요?
- 답은 Application Context입니다. 만약 우리가 Activity의 Context를 전달했다면, 액티비티가 사용되지 않는 경우에도 MyDB가 불필요하게 액티비티를 참조하고, 메모리 누수가 발생할 것입니다. 그러므로 싱글턴의 경우에는 항상 애플리케이션 컨택스트를 전달하는 게 맞습니다.
-
그렇다면 언제 액티비티 컨택스트를 사용해야 할까요?
- 언제든 액티비티를 사용할 때, Toast, Dialog 등의 UI operation에서 컨택스트가 필요하다면 이때 액티비티 컨택스트를 사용해야 합니다.
-
항상 가능한 한 가까운 컨택스트를 사용하도록 합시다. 액티비티에 있다면, 액티비티 컨택스트를, 애플리케이션에 있다면, 애플리케이션 컨택스트를 사용합니다. 싱글턴의 경우에는 애플리케이션 컨택스트를 사용합니다.
✅getApplicationContext()를 쓰면 안 되는 경우
Application Context는 Activity Context가 제공하는 기능 전체를 제공하진 않습니다. 특히 GUI와 관련된 컨택스트 조작은 실패할 확률이 높습니다.
Application Context가 사용자 호출로 생성된, clean up 되지 않은 객체를 가지고 있다면 메모리 누수가 발생할 수 있습니다. Activity 객체는 가비지 콜렉션이 가능하지만 Application 오브젝트는 프로세스가 살아있는 동안 남아있습니다.
✅Rule of Thumb
대부분의 경우 가장 가까운, 스코프에 해당하는 컨택스트를 직접 사용하세요. 참조가 해당 컴포넌트의 라이프사이클을 넘어서지 않는 이상 메모리 누수 걱정 없이 컴포넌트를 유지할 수 있습니다. 액티비티나 서비스 이외의 객체에서 컨택스트를 참조해야 하는 경우 액티비티 컨택스트가 아닌, 애플리케이션 컨텍스트로 전환하세요.
참조
https://roomedia.tistory.com/entry/Android-Context%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C
https://shinjekim.github.io/android/2019/11/01/Android-context%EB%9E%80/