Context

sumi Yoo·2022년 10월 7일
0

Context란?

Interface to global information about an application environment.
어플리케이션 환경에 대한 전역 정보에 대한 인터페이스입니다.

  • 어플리케이션의 현재 상태를 갖고 있다.
  • 시스템이 관리하고 있는 액티비티, 어플리케이션의 정보를 얻기 위해 사용한다.
  • 안드로이드 시스템 서비스에서 제공하는 API(리소스, DB, Shared Preferences)에 접근하기 위해 사용한다.
  • Activity, Application 클래스는 Context 클래스를 상속받은 클래스

Context 의 잘못된 사용은, 메모리 릭 문제로 이어질 수 있기 때문에 정말 주의해야 한다.

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

  1. Application Context
  2. Activity Context

Application Context

Activity 에서 applicationContext 라는 프로퍼티를 통해 얻을 수 있는 (코틀린 기준, 자바의 경우 getApplicationContext() 라는 메소드를 통해 얻을 수 있음) 싱글톤 인스턴스이다.

이 Context 는 어플리케이션 라이프사이클과 묶여있어, 현재 Context 가 종료되고 나서도 Context 가 필요한 작업이나, 액티비티 범위를 벗어난 곳에 Context 가 필요한 작업에 적합하다.

예를 들어, 어플리케이션 내에 싱글톤 객체를 만드려고 하는데 이 객체가 Context 를 필요로 할 때, Application Context 를 사용하면 된다. 만약 이런 상황에 Activity Context 를 넘겨주게 되면, Activity 에 대한 참조를 메모리에 남겨두며 GC (Garbage Collected) 되지 않은 채 분명 메모리 릭이 발생할 것이다.

그럼, 어플리케이션 전역에서 사용할 어떤 라이브러리를 MainActivity 에서 초기화 할 때 Context 가 필요하다고 가정해보자. 어떤 Context 를 넘겨줘야 할까?

정답은 Application Context 이다. 만일 Activity Context 를 넘겨주게 되면, MainActivity 에 대한 참조가 메모리 상에서 GC 되지 않아 메모리 릭이 발생하기 때문이다.

따라서, 오랫동안 지속되거나 앱 전역에서 사용될 녀석의 경우 Application Context 를 넘겨주면 된다.

Activity Context

해당 Context 는 액티비티 안에서만 사용 가능하다. 특정 Activity 의 라이프 사이클에 종속되어 있다. 이 녀석은 Activity 스코프 내에서 사용될 때 넘겨주거나, Activity 와 라이프사이클이 같은 객체를 생성할 때 넘겨준다. 즉, Activity 가 소멸되면 해당 Context 도 같이 소멸되는 것이다.

정리하고 넘어가기

그렇다면, 각각 컴포넌트의 입장에서 Context 의 사용 가능 여부를 살펴보자.

MyApplication : Application Context 사용 가능
MainActivity1 : Application Context, Activity 1 Context 사용 가능
MainActivity2 : Application Context, Activity 2 Context 사용 가능

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

Application Context 는 Activity Context 가 지원하는 모든 것을 지원하지 않는다. 만능처럼 보이지만 절대 아니다. 따라서 GUI (View Component 등) 관련 동작들에 있어 Application Context 는 오류를 발생할 확률이 높다.

예를들어, Application Context 를 활용하여 AlertDialog 를 show() 하게 되면

java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

과 같은 오류를 맛볼 수 있다. 따라서 조심하여 사용하도록 하자.

Activity 는 Garbage Collection 이 가능하지만, Application 은 앱 프로세스가 살아있는 동안 계속하여 남아있다. 따라서, Application Context 를 활용한 객체를 메모리에서 할당 해제하지 않고 있을 경우, 메모리 릭을 발생할 가능성이 농후하다.

Quiz

👮🏻‍♀️ Q1. MyApplication 클래스와 MyDB 싱글톤 객체가 있을 때, MyDB 가 Context 를 필요로 하는 경우, 어떤 Context 를 넘겨줘야 할까?
정답: Application Context
만약 Activity Context를 전달했다면, 액티비티가 사용되지 않을 때에도 MyDB가 해당 액티비티를 참조하고, 메모리 릭이 발생할 것이다. 따라서, 싱글톤 객체에서 Context 를 필요로 하는 경우, 무조건 Application Context 를 사용해야 한다. 필수다!

👮🏻‍♀️ Q2. Toast , Dialog 등의 UI 동작에 있어 Context 가 필요하다면, 어떤 Context 를 넘겨줘야 할까?
정답: Activity Context
해당 UI 컴포넌트들은 어차피 Activity 의 라이프 사이클에 종속되는 것들이기 때문에, Activity Context 를 사용해주면 된다.

Tip

항상 가장 가까운, 밀접한 스코프의 Context 를 골라 사용하면 된다. 액티비티에서 사용된다면 Activity Context 를, 어플리케이션 전역에서 (싱글톤 등) 사용된다면 Application Context 를 사용하면 된다. 이렇게만 사용하면 메모리 릭 걱정은 없다.

context란?

다른 클래스에서 application context 가져오기

class MainActivity : AppCompatActivity() {

    init {
        instance = this
    }
    
    companion object {
        lateinit var instance: MainActivity

        fun getContext(): Context {
            return instance.applicationContext
        }
    }
}
object StoreItemsLocalDataSource : StoreItemsDataSource {

    override fun getStoreItems(): MutableList<MainViewData> {
        val context = MainActivity.getContext()
        val mainStoreItem = getJsonString(context.assets.open(ItemType.MAIN.fileName))
    }
}

0개의 댓글

관련 채용 정보