사진: Unsplash의Anne Nygård
안드로이드에서 Context를 얻을 수 있는 방법은 생각보다 많습니다. 다만 모두가 다 같은 Context를 말하는 것은 아닙니다.
프래그먼트에서 액티비티의 Context에 접근할 때, 왜 캐스팅을 해야만 Context를 사용할 수 있을까? 란 의문점에서 이번 게시글에서 정리해보고자 합니다.
액티비티에서 Context를 얻는 방법
액티비티에서 직접 Context 얻기 - `this`
Context가 필요한 곳이 액티비티라면 Context을 얻을 수 있는 가장 간단한 방법은 `this`입니다.
이것이 어떻게 가능한 지는 액티비티의 상속 구조를 살펴보면 알 수 있습니다.
액티비티는 추상 클래스인 Context를 구현한 ContextImpl 클래스를 내부적으로 이용한 ContextWrapper를 상속받습니다.
`this`는 액티비티의 인스턴스를 참조하고 있기 때문에 `this`로 액티비티의 부모 클래스인 Context를 얻을 수 있습니다.
ContextWrapper에서 Context 얻기 - `getBaseContext()`
위에서 본 그림에 있는 ContextWrapper의 메서드를 통해서도 Base Context를 얻을 수 있습니다.
ContextWrapper의 `getBaseContext` 메서드는 ContextWrapper에 의해 래핑된 원래 컨텍스트를 반환합니다.
// 'ContextWrapper.java'
public Context getBaseContext() {
return mBase;
}
View에서 Context 얻기 `View.getContext()`
안드로이드의 View들은 액티비티 아래에 존재합니다. 그렇기에 각각의 View들을 통해서 그들의 부모인 액티비티의 Context를 얻을 수 있습니다.
// 'View.java'
public final Context getContext() {
return mContext;
}
프래그먼트에서 Context를 얻는 방법
프래그먼트는 자체적인 Context를 갖지는 않습니다. 프래그먼트는 부모 액티비티에 붙어서 존재하는데, 이때 연결된 정보를 통해 부모 액티비티의 정보를 가져올 수 있습니다.
부모 액티비티의 Context 가져오기 - `getContext()`
프래그먼트에 있는 `getContext` 메서드를 통해 부모 액티비티의 Context를 가져올 수 있습니다. 여기서 `mHost`는 연결된 부모 액티비티를 가리킵니다.
// 'Fragment.java'
@Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
부모 액티비티 가져오기 - `getActivity()`
프래그먼트에 있는 `getActivity` 메서드를 통해서 부모 액티비티를 가져올 수 있습니다.
// 'Fragment.java'
@Nullable
final public FragmentActivity getActivity() {
return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}
Nullable하지 않게 Context와 Activity 가져오기
위에 있는 2가지 방법은 mHost로 연결을 체크하고 연결되어 있지 않다면 null을 반환합니다.
`requireContext()`와 `requireActivity()` 메서드를 사용한다면 null을 반환하는 대신에 ` IllegalStateException
`을 던져서 Context가 존재하지 않다는 것을 알려줍니다.
// 'Fragment.java'
@NonNull
public final Context requireContext() {
Context context = getContext();
if (context == null) {
throw new IllegalStateException("Fragment " + this + " not attached to a context.");
}
return context;
}
@NonNull
public final FragmentActivity requireActivity() {
FragmentActivity activity = getActivity();
if (activity == null) {
throw new IllegalStateException("Fragment " + this + " not attached to an activity.");
}
return activity;
}
getContext와 getActivity의 차이
이 부분이 저의 궁금증을 해소시켜줄 부분입니다.
일반적인 상황에서 Context가 필요하다면 `getContext`와 `getActivity` 메서드로 부모 액티비티의 Context를 얻을 수 있습니다.
만약 이러한 메서드를 사용해서 부모 액티비티의 메서드를 호출하려고 한다고 생각해 보겠습니다.
`getActivity` 메서드를 사용한다면 이는 매우 간단합니다. `getActivity` 메서드의 반환 값은 프래그먼트 객체와 관련있는 현재 액티비티에 대한 참조를 반환합니다. 만약 프래그먼트 객체와 관련된 액티비티가 존재하지 않는다면 Null을 반환해주게 됩니다.
`getContext` 메서드는 현재 객체와 관련된 컨텍스트를 반환합니다. 이 객체는 Context를 정의한 객체라면 모두 가능합니다.
다만 `getContext` 메서드의 경우에는 컨텍스트의 구현체로서 메인 액티비티가 되기 때문에 해당 Context가 메인 액티비티 임을 보장할 수가 없습니다.
Reference
'Android' 카테고리의 다른 글
멀티 모듈 프로젝트에 Datastore로 자동 로그인 구현하기 (0) | 2023.11.27 |
---|---|
안드로이드의 Doze와 App Standby (1) | 2023.11.08 |
안드로이드가 화면을 그리는 방법을 제대로 알아보기 (0) | 2023.10.25 |
클린 아키텍처와 안드로이드 권장 멀티 모듈 적용하기 (3) (0) | 2023.10.08 |
클린 아키텍처와 안드로이드 권장 멀티 모듈 적용하기 (2) (1) | 2023.10.05 |