Context 클래스
앱 개발을 하다보면, Context는 필요하다. 이가 없으면 액티비티를 시작할 수도, 브로드캐스트를 발생시킬 수도, 서비스를 시작할 수도 없다. 리소스에 접근할 때도 Context를 통해서만 가능하다.
Context는 여러 컴포넌트의 상위 클래스이면서 Context를 통해서 여러 컴포넌트가 연결돼 있으므로 Context 자체를 살펴보는 것이 컴포넌트를 이해하는 데도 도움이 된다.
Context
- 추상 글래스
- 메서드 구현이 거의 없다
- 상수 정의와 추상 메서드로 구성
이 클래스 하위 클래스로는 ContextWrapper가 있고 이를 상속하는 아래 3가지가 있다.
- Activity
- Service
- Application
클래스 다이어그램
Activity, Service, Application을 보면 ContextImpl을 직접 상속하지 않고, ContextImpl 메서드를 호출하는 형태를 갖고 있다.
이렇게 하면 ContextImpl 변수가 노출되지 않고, ContextWrapper에서는 ContextImpl의 공개 메서드만 호출하게 된다.
또한, 각 컴포넌트별로 사용하는 기능을 제어하기도 단순해진다.
사용 가능한 Context 여러개
ex) Activity
- Activity 인스턴스 자신(this)
- getBaseContext()를 통해 가져오는 ContextImpl 인스턴스
- getApplicationContext()를 통해 가져오는 Application 인스턴스 Activity의 getApplication() 메서드로 가져오는 인스턴스와 같다.
3개의 인스턴스가 다르기 때문에 함부로 캐스팅하면 안된다.
getBaseContext()
로 가져온 걸 Activity로 캐스팅하면 ClassCastException이 발생한다.
cf) https://velog.io/@woga1999/Android%EC%9D%98-Context
ContextWrapper
Context와 컴포넌트 중간에 있는 ContextWrapper는 그 이름처럼 Context를 래핑한 ContextWrapper(Context base)
생성자를 갖고 있다.
ContextWrapper.java
@UnsupportedAppUsage
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
base 파라미터에 전달되는 것은 Context의 여러 메서드를 직접 구현한 ContextImpl 인스턴스이다.
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
ContextWrapper의 여러 메서드는 base의 메서드를 그대로 호출한다.
Activity, Service, Application은 public ContextWrapper(Context base) { mBase = base; }
이 생성자를 사용하지 않고, 실제로는 attachBaseContext()
메서드를 사용한다.
Activity, Service, Application 모두 내부적으로 ActivityThread에서 컴포넌트가 시작된다. 이때 각 컴포넌트의 attach()
메서드를 실행하고 attach() 메서드에서 다시 attachBaseContext()
메서드를 호출한다.
ContextImpl?
ContextWrapper 생성자에 전달되는 ContextImpl은 앱에서 싱글톤으로 단 1개의 인스턴스만 있는가? => 그렇지 않다
ContextWrapper에 getBaseContext()
와 getApplicationContext()
라는 2개의 별도 메서드를 보고 유추할 수 있따.
Acitivity, Service, Application 컴포넌트는 각각 생성한 ContextImpl을 하나씩 래핑하고 있고 getBaseContext()는 각각 ContextImpl 인스턴스를 리턴한다.
getApplicationContext()
는 Application 인스턴스를 리턴하는 것이므로 앱에서 1개 밖에 없는 어디서나 동일한 인스턴스를 반환한다.
ContextImpl 메서드
Helper, Permission, system_service 이렇게 3개 그룹으로 나눌 수 있다.
- 앱 패지키 정보 제공, 내/외부 파일, SharedPreferences, 데이터베이스 등을 위한 헬퍼 메서드
- Activity, BroadCastReceiver, Service와 같은 컴포넌트 시작 메서드, 퍼미션 체크 메서드 -> system_service 프로세서의
ActivityManagerService
의 메서드 다시 호출 - 시스템 서비스를 호출하기 위한 getSystemService() 메서드
Reference
- https://s2choco.tistory.com/10
- https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/ContextWrapper.java
- 안드로이드 프로그래밍
<Next Step>
Author And Source
이 문제에 관하여(Context 클래스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@woga1999/Context-클래스저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)