Android/안드로이드 프로그래밍 Next Step

[Next Step] 4. Context 클래스

Diane_KIM 2023. 8. 25. 22:52

Context의 하위클래스는 Activity, Service, Application (BroadcastReceiver와 ContentProvider는 Context를 상속X)

  • Activity, Service, Application 은 ActivityThread에서 컴포넌트가 시작된다
  • 이때 각 컴포넌트의 attach() 메서드에서 attachBaseContect()를 호출
  • 컴포넌트 별로 생성한 ContextImpl 를 하나씩 래핑하고 있고, getBaseContext()는 ContextImpl 인스턴스를 리턴 (싱글톤X)
  • getApplication()는 Application 인스턴스를 리턴하는 것으로 단 한개만 존재

 

ContextImpl 메서드

  1. 헬퍼 메서드 : 앱 패키지 정보를 제공하거나 내/외부 파일, SharedPreferences, 데이터베이스 등을 사용
  2. 퍼미션 메서드 : Activity, BR, Service 같은 컴포넌트를 시작하는 메서드와 퍼미션 체크해줌. 이 메서드는 system_server 프로세스의 ActivityManagerService 의 메서드를 다시 호출
  3. 시스템 서비스 접근 메서드 
    • 시스템 서비스에 접근하기 위한 getSystemService() 메서드
    • ContextImpl의 정적 초기화 블록에서 클래스가 최초 로딩될 때 시스템 서비스를 매핑하고, getSystemService()에서 사용
    • ex) getSystemService(Context.ALARM_SERVICE)

 

사용 가능한 Context 3개

  1. Activity 인스턴스 자신(this)
  2. getBaseContext()를 통해 가져오는 ContextImpl 인스턴스
  3. getApplicationContext()를 통해 가져오는 Application 인스턴스

1. setContentView()에게 레이아웃의 리소스 ID 를 넘겨준다

2. inflate() 를 수행하여 XML 마크업 코드를 View 객체로 만드는 동작을 수행

    => View - inflate() 메소드가 해당작업 진행

/**
 * Inflate a view from an XML resource.  This convenience method wraps the {@link
 * LayoutInflater} class, which provides a full range of options for view inflation.
 *
 * @param context The Context object for your activity or application.
 * @param resource The resource ID to inflate
 * @param root A view group that will be the parent.  Used to properly inflate the
 * layout_* parameters.
 * @see LayoutInflater
 */
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
    LayoutInflater factory = LayoutInflater.from(context);
    return factory.inflate(resource, root);
}
// LayoutInflater.java - from method
/**
 * Obtains the LayoutInflater from the given context.
 */
public static LayoutInflater from(Context context) {
    LayoutInflater LayoutInflater =
            (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (LayoutInflater == null) {
        throw new AssertionError("LayoutInflater not found.");
    }
    return LayoutInflater;
}

 

결과적으로 setContentView() => View - inflate() => LayoutInflater - from() 내부에서는 다음과 같은 일을 함.

val inflater : LayoutInflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = inflater.inflate(R.layout.activity_home, linearLayout, true)

좀 더 줄여보면

val view = LayoutInflater.from(this).inflate(R.layout.activity_home, linearLayout, false)

=> View는 Activity 인스턴스가 전달됨

 

 

View에 Context가 전달되는 루트

  1. Activity에 setContentView() 내부에서 사용되는 LayoutInflater에 Activity인스턴스가 전달됨
  2. View생성자의 Context파라미터에 Activity 인스턴스가 전달됨