Developing Myself Everyday
article thumbnail

사진: UnsplashAnne 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

 

Different ways to get Context in Android

Context is one of the important and most used property. You need Context to perform a lot of things on Android. Be is displaying a toast…

medium.com

 

What is different between getContext and getActivity from Fragment in support library?

What is different between getContext() and getActivity() from Fragment in support library? Do they always return the same object? (activity associated with current fragment)

stackoverflow.com

 

profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!