본문 바로가기

코딩 이야기/안드로이드&코틀린 공부

[안드로이드&코틀린 공부] Context, Context wrapper

반응형

Context

전 주제만 봤을때 content와 이름이 비슷한 나머지 역할도 비슷한가?

착각을 했지만 아니였습니다. content와 context는 완전히 다릅니다.

안드로이드 Context, 컨텍스트는 이름 그대로 맥락을 뜻합니다

컨텍스트는 어플리케이션의 현재 상태, 환경에 대한 글로벌한 정보를 지니고 있는 추상클래스입니다.

컨텍스트는 시스템의 핸들과도 같습니다.

리소스, 데이터베이스, preferences 등에 대한 접근을 제공한다고 합니다.

따라서 어플리케이션에 대한 정보가 필요할 때는 컨텍스트를 사용하면 됩니다.

그래서 인자로 컨텍스트를 요청하는 함수들이 많습니다.

잘못 사용하면 앱이 비정상으로 종료되거나 메모리 누수가 발생할 수 있습니다.

컨텍스트에는 크게 어플리케이션 컨텍스트와 액티비티 컨텍스트가 있습니다.

Application Context

이름 그대로 어플리케이션에 대한 컨텍스트입니다.

그렇기에 어플리케이션의 라이프사이클을 따르며 어플리케이션이 실행되어 종료될 때까지 동일한 객체를 참조합니다.

그렇기에 현재의 컨텍스트와 분리된 라이프사이클을 가진 컨텍스트가 필요할 때 사용한다고 합니다.

또한 싱글톤 객체입니다. 앱이 죽기 전까지 하나의 객체만 반환합니다.

어플리케이션 컨텍스트를 반환받기 위해서는

getApplicationContext()

를 사용하면 됩니다.

문제상황

액티비티에서 뷰모델에 액티비티 컨텍스트를 넘겨준 상태에서 참조 중에 액티비티가 종료되었다고 합시다.

이 경우에도 뷰모델에서 계속 액티비티 컨텍스트를 참조하고 있기 때문에 메모리누수가 발생합니다.

→ 이런때에 어플리케이션 컨텍스트를 사용해야합니다.

즉 액티비티 컨텍스트보다 더 긴 수명주기에 대응해야할 때 사용하게 되는 것 같습니다.

Activity Context

액티비티 컨텍스트는 액티비티의 라이프사이클을 따르다가 액티비티가 종료상태일때 컨텍스트는 삭제됩니다.

액티비티 범위 내에서 컨텍스트를 전달하거나 수명주기가 액티비티에 붙은 객체를 생성해야할 때 액티비티 컨텍스트를 사용한다고 합니다.

그러면 전부 애플리케이션 컨텍스트를 사용하면 되지 않을까?

아닙니다. 액티비티가 하는 일에 어플리케이션 컨텍스트가 전부 관여할 순 없기 때문에 액티비티 컨텍스트를 사용해야 할 때가 있습니다. UI 관련된 처리는 액티비티 컨텍스트만 가능합니다.

즉 액티비티 컨텍스트를 사용해야 하지만 수명주기를 잘 숙지하고 사용해야합니다.

Context Wrapper

Context는 공부했지만 Wrapper는 뭘까?

여기 wrap은 남은 반찬에 씌우는 랩이나 상하이 치킨랩 이런거에 들어가는 wrap이 맞습니다.

즉 포장한다의 의미를 담고있습니다.

(ContextWrapper의 위치는 이렇습니다.)

프로그램을 만들다가 간혹가다 기본 타입의 데이터를 객체로 취급해야 하는 경우가 있습니다.

예를 들어, 메소드의 인수로 객체 타입만이 요구되면, 기본 타입의 데이터를 그대로 사용할 수 없습니다.

이때에는 기본 타입의 데이터를 먼저 객체로 변환한 후 작업을 수행해야 합니다.

이렇게 원래는 기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스를 Wrapper 클래스라고 합니다. 그리고 그 타입에 대해서 접근을 제어하거나 추가적인 기능을 제공하기도 합니다.

자바에서 int 타입의 래퍼 클래스는 Integer 입니다

Integer num = new Integer(5);

int n = num.intValue();

자바에서 원래 Wrapper 클래스는 이런 느낌입니다.

하지만 Context Wrapper는 비슷하기도 하고..? 틀린 부분도 있습니다.

Android 에서 ContextWrapper는 Context를 확장하고 있는 클래스입니다.

래퍼 클래스와 마찬가지로 ContextWrapper를 사용하면 기본의 컨텍스트 객체를 감싸고, 특정 동작을 추가하거나 변경할 수 있습니다.

예를 들어 ContextWrapper를 사용하여 리소스나 UI를 동적으로 변경하거나, 여러 작업을 수행할 수 있습니다.

class CustomContextWrapper(base: Context) : ContextWrapper(base) {

    override fun getResources(): Resources {
        val configuration = Configuration()
        configuration.setLocale(Locale("en"))
        applyOverrideConfiguration(configuration)

        return super.getResources()
    }
}

위의 예제는 contextWrapper를 상속받은 후 getResources()를 오버라이딩하여 언어를 동적으로 변경을 하도록 하는 코드입니다.

이런식으로 활용할 수 있습니다.

contextWrapper에서는 안드로이드 공식 문서에 나와있듯 너무나도 많은 메소드와 프로퍼티를 가지고 있어서 전부 설명하는 건 불가능하지만, 가장 기본적이고 중요한 메소드 2가지를 알아보겠습니다.

attachBaseContext()

이 메소드는 ContextWrapper의 기본 컨텍스트를 설정합니다. 그 이후 모든 호출은 기본 컨텍스트를 따르게 됩니다.

getBaseContext()

현재 ContextWrapper가 감싸고 있는 기본 컨텍스트를 반환합니다.

Context

전 주제만 봤을때 content와 이름이 비슷한 나머지 역할도 비슷한가?

착각을 했지만 아니였습니다. content와 context는 완전히 다릅니다.

안드로이드 Context, 컨텍스트는 이름 그대로 맥락을 뜻합니다

컨텍스트는 어플리케이션의 현재 상태, 환경에 대한 글로벌한 정보를 지니고 있는 추상클래스입니다.

컨텍스트는 시스템의 핸들과도 같습니다.

리소스, 데이터베이스, preferences 등에 대한 접근을 제공한다고 합니다.

따라서 어플리케이션에 대한 정보가 필요할 때는 컨텍스트를 사용하면 됩니다.

그래서 인자로 컨텍스트를 요청하는 함수들이 많습니다.

잘못 사용하면 앱이 비정상으로 종료되거나 메모리 누수가 발생할 수 있습니다.

컨텍스트에는 크게 어플리케이션 컨텍스트와 액티비티 컨텍스트가 있습니다.

Application Context

이름 그대로 어플리케이션에 대한 컨텍스트입니다.

그렇기에 어플리케이션의 라이프사이클을 따르며 어플리케이션이 실행되어 종료될 때까지 동일한 객체를 참조합니다.

그렇기에 현재의 컨텍스트와 분리된 라이프사이클을 가진 컨텍스트가 필요할 때 사용한다고 합니다.

또한 싱글톤 객체입니다. 앱이 죽기 전까지 하나의 객체만 반환합니다.

어플리케이션 컨텍스트를 반환받기 위해서는

getApplicationContext()

를 사용하면 됩니다.

문제상황

액티비티에서 뷰모델에 액티비티 컨텍스트를 넘겨준 상태에서 참조 중에 액티비티가 종료되었다고 합시다.

이 경우에도 뷰모델에서 계속 액티비티 컨텍스트를 참조하고 있기 때문에 메모리누수가 발생합니다.

→ 이런때에 어플리케이션 컨텍스트를 사용해야합니다.

즉 액티비티 컨텍스트보다 더 긴 수명주기에 대응해야할 때 사용하게 되는 것 같습니다.

Activity Context

액티비티 컨텍스트는 액티비티의 라이프사이클을 따르다가 액티비티가 종료상태일때 컨텍스트는 삭제됩니다.

액티비티 범위 내에서 컨텍스트를 전달하거나 수명주기가 액티비티에 붙은 객체를 생성해야할 때 액티비티 컨텍스트를 사용한다고 합니다.

그러면 전부 애플리케이션 컨텍스트를 사용하면 되지 않을까?

아닙니다. 액티비티가 하는 일에 어플리케이션 컨텍스트가 전부 관여할 순 없기 때문에 액티비티 컨텍스트를 사용해야 할 때가 있습니다. UI 관련된 처리는 액티비티 컨텍스트만 가능합니다.

즉 액티비티 컨텍스트를 사용해야 하지만 수명주기를 잘 숙지하고 사용해야합니다.

Context Wrapper

Context는 공부했지만 Wrapper는 뭘까?

여기 wrap은 남은 반찬에 씌우는 랩이나 상하이 치킨랩 이런거에 들어가는 wrap이 맞습니다.

즉 포장한다의 의미를 담고있습니다.

(ContextWrapper의 위치는 이렇습니다.)

프로그램을 만들다가 간혹가다 기본 타입의 데이터를 객체로 취급해야 하는 경우가 있습니다.

예를 들어, 메소드의 인수로 객체 타입만이 요구되면, 기본 타입의 데이터를 그대로 사용할 수 없습니다.

이때에는 기본 타입의 데이터를 먼저 객체로 변환한 후 작업을 수행해야 합니다.

이렇게 원래는 기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스를 Wrapper 클래스라고 합니다. 그리고 그 타입에 대해서 접근을 제어하거나 추가적인 기능을 제공하기도 합니다.

자바에서 int 타입의 래퍼 클래스는 Integer 입니다

Integer num = new Integer(5);

int n = num.intValue();

자바에서 원래 Wrapper 클래스는 이런 느낌입니다.

하지만 Context Wrapper는 비슷하기도 하고..? 틀린 부분도 있습니다.

Android 에서 ContextWrapper는 Context를 확장하고 있는 클래스입니다.

래퍼 클래스와 마찬가지로 ContextWrapper를 사용하면 기본의 컨텍스트 객체를 감싸고, 특정 동작을 추가하거나 변경할 수 있습니다.

예를 들어 ContextWrapper를 사용하여 리소스나 UI를 동적으로 변경하거나, 여러 작업을 수행할 수 있습니다.

class CustomContextWrapper(base: Context) : ContextWrapper(base) {

    override fun getResources(): Resources {
        val configuration = Configuration()
        configuration.setLocale(Locale("en"))
        applyOverrideConfiguration(configuration)

        return super.getResources()
    }
}

위의 예제는 contextWrapper를 상속받은 후 getResources()를 오버라이딩하여 언어를 동적으로 변경을 하도록 하는 코드입니다.

이런식으로 활용할 수 있습니다.

contextWrapper에서는 안드로이드 공식 문서에 나와있듯 너무나도 많은 메소드와 프로퍼티를 가지고 있어서 전부 설명하는 건 불가능하지만, 가장 기본적이고 중요한 메소드 2가지를 알아보겠습니다.

attachBaseContext()

이 메소드는 ContextWrapper의 기본 컨텍스트를 설정합니다. 그 이후 모든 호출은 기본 컨텍스트를 따르게 됩니다.

getBaseContext()

현재 ContextWrapper가 감싸고 있는 기본 컨텍스트를 반환합니다.

반응형