Everyday Growing Engineer 2023. 2. 27. 14:56

Android Context 

  • 어플리케이션의 현재 상태를 갖고 있음.
  • Activity와 Application의 정보를 얻기 위해 사용
  • Context는 Resource, Database, Shared preference 등의 시스템 자원에 접근할 수 있게 해줌.
  • Context는 새로 생성된 객체가 지금 어떤 일이 일어나고 있는지에 대한 정보(어플리케이션 패키지 이름, 리소스 정보) 를 알 수 있도록 합니다. (예 : getPackageName(), getResource()) 
  • Activity, Application 클래스는 Context클래스를 상속받은 클래스. Context는 여러 컴포넌트의 상위 클래스이다.

Context가 필요한 이유:

  • 일반적인 OS와는 다르게, 안드로이드는 어플리케이션과 프로세스가 독립적입니다. 따라서 프로세스가 종료되어도 어플리케이션은 실행 중일 수 있습니다. 예를 들어, Service나 Broadcast Receiver가 어플리케이션 실행 여부와 무관하게 백그라운드에서 실행 가능합니다.
  • 이런 특성으로 인해서 프로세스와 어플리케이션은 따로 관리됩니다. 프로세스는 운영체제가 관리를 하고, 어플리케이션은 ActivityManagerService가 관리합니다.
  • 그래서 다른 플랫폼에서는 시스템 함수를 호출하기 위해서 매개체를 거칠 필요가 없습니다. 하지만 안드로이드에서는 어플리케이션 정보에 접근하려면 ActivityManagerService를 통해서 접근이 가능합니다. 여기에는 많은 어플리케이션 정보를 key-value형태로 구분을 하는데, 여기서 Context가 등장합니다.
  • ContextActivityManagerService에 접근하기 위한 중간 다리 역할을 합니다. 각 어플리케이션을 대표하는 ID역할을 하게 됩니다.

즉, 어플리케이션과 프로세스 독립적이고. 어플리케이션 정보를 가져오려면 context 이용해 ActivityManagerService 접근해야되서 context 가 필요함

 

ContextWrapper와 ContextImpl

Context는 추상 클래스이기 때문에 이를 사용하기 위해서는 구현체가 있어야 한다. 기본 구현체는 ContextImpl이고, 이 구현체는 사용자에게 노출하지 않고 ContextWrapper로 감싸져 있다.

 

이러한 Context 는, 크게 나누자면 또 두 가지로 나눌 수 있다.

  1. Application Context
  2. Activity Context

Application Context : 

  • Application Context는 Activity 에서 applicationContext(Kotlin), getApplicationContext()(Java) 를 통해 얻을 수 있는 싱글톤 인스턴스이다.
  • 이 Context 는 application lifecycle과 묶여있어, 현재 Context 가 종료되고 나서도 Context 가 필요한 작업이나, 액티비티 범위를 벗어난 곳에 Context 가 필요한 작업에 적합하다.
  • 예제 1 : Activity 안에서 라이브러리를 초기화해야 하는 경우 => Application Context 를 전달하여 사용
  • 예제 2:  어플리케이션 내에 싱글톤 객체를 만드려고 하는데 이 객체가 Context 를 필요로 할 때, Application Context 를 사용하면 된다. 만약 이런 상황에 Activity Context 를 넘겨주게 되면, Activity 에 대한 참조를 메모리에 남겨두며 GC (Garbage Collected) 되지 않은 채 분명 메모리 릭이 발생할 것이다.
  • 예제 3: 어플리케이션 전역에서 사용할 어떤 라이브러리를 MainActivity 에서 초기화 할 때 Context 가 필요하다면 Application Context 이다. 만일 Activity Context 를 넘겨주게 되면, MainActivity 에 대한 참조가 메모리 상에서 GC 되지 않아 메모리 릭이 발생하기 때문이다. 오랫동안 지속되거나 앱 전역에서 사용될 녀석의 경우 Application Context 를 넘겨주면 된다.

메모리 릭???

  • 어플리케이션은 동작을 위해 메모리가 필요합니다. 어플리케이션이 사용이 끝난 메모리를 반환하지 않는 것을 메모리 릭이라고 합니다. 보통 릭이 발생하면, 사용한 메모리는 반환하지 않은 채 추가로 필요한 메모리를 시스템에 요청하기 때문에 사용하는 메모리 양이 계속 증가합니다.
  • 이 과정이 계속되면, (1) 버벅거림 (2) OOM(Out Of Memory)를 발생시키고 어플리케이션이 강제 종료후 App에 할당되었던 메모리가 회수

GC (Garbage Collected) ???

  • GC는 더이상 사용되지 않는 쓰레기 객체들을 정리하는 작업을 한다.
  • GC는 필요에 따라 자동으로 실행된다.

Activity Context :

  • 해당 Context 는 액티비티 안에서만 사용 가능하다. 특정 Activity 의 라이프 사이클에 종속되어 있다. 이 녀석은 Activity 스코프 내에서 사용될 때 넘겨주거나, Activity 와 라이프사이클이 같은 객체를 생성할 때 넘겨준다. 즉, Activity 가 소멸되면 해당 Context 도 같이 소멸되는 것이다.
  • 예제 1: Toast , Dialog 등의 UI 동작에 있어 Context 가 필요하다면 Activity Context 사용. 해당 UI 컴포넌트들은 Activity의 라이프 사이클에 종속되는 것들이기 때문에, Activity Context 를 사용해주면 된다.

Application Context 를 사용하면 안되는 경우

  • Application Context 는 Activity Context 가 지원하는 모든 것을 지원하지 않는다.  오류를 발생 가능.
  • 예를들어, Application Context 를 활용하여 AlertDialog 를 show() 하게 되면
  • Activity 는 Garbage Collection 이 가능하지만, Application 은 앱 프로세스가 살아있는 동안 계속하여 남아있다메모리 릭의 발생을 막기 위해 상황에 따라 메모리 할당 해제 필요.

ActivityName.this

- Activity Context를 반환한다. Activity Scope 안에서 사용할 때는 this만으로도 가져올 수 있다.

getApplicationContext()
Application Context를 반환한다.

getApplication()
- Application 인스턴스를 반환한다. 

getBaseContext()
- ContextWrapper의 Context 인스턴스를 반환한다.

View의 getContext()
- View에도 getContext() 메서드가 있어 Context를 가져올 수 있는데, View를 생성할 때 생성자의 인자로 들어가는 Context가 getContext()의 결과로 반환된다.