Android

Android Application Context

네모메모 2024. 8. 11. 10:22
반응형

 

 

Application Context의 적절한 사용

  • Application의 Context는 애플리케이션이 실행되는 동안 메모리에 유지됩니다.
    따라서 전역적으로 사용되거나 장기적인 참조가 필요한 객체들에 적합하며, UI와 관계없는 작업에서 안전하게 사용할 수 있습니다.
  • Application 단의 Context를 확장 함수에서 사용하게 되면, 단위 테스트를 수행하기 어려워질 수 있습니다.
    Context에 의존하는 코드는 테스트에서 모의(Mocking) 처리가 필요하며, 이는 테스트의 복잡성을 높입니다.

 

1. Application Context를 사용하는 것이 적절한 경우

  • 장기적으로 유지되는 객체:
    • 장기적으로 유지되거나 전역적으로 사용되는 객체에서 Context가 필요할 때는 Application Context를 사용하는 것이 안전합니다. 예를 들어, 싱글톤 객체, Service, 데이터베이스 관리 객체, 네트워크 관련 객체 등은 Application Context를 사용하는 것이 적합합니다.
  • UI와 무관한 작업:
    • 리소스에 접근하거나, 시스템 서비스(예: AlarmManager, ConnectivityManager)에 접근하는 것과 같이 UI와 관계없는 작업을 수행할 때는 Application Context를 사용해도 문제가 없습니다.
  • 외부 구성 요소에서 Context가 필요할 때:
    • 외부 라이브러리나 유틸리티 클래스가 Context를 필요로 할 때, 이들이 장기적으로 사용된다면 Application Context를 전달하는 것이 바람직합니다. 이는 메모리 누수를 방지하는 데 도움이 됩니다.

 

2. Application Context를 사용하는 것이 부적절한 경우

  • UI 관련 작업:
    • Application Context는 UI 요소를 생성하거나 관리하는 데 적합하지 않습니다. 예를 들어, LayoutInflater로 뷰를 인플레이트하거나, Toast 메시지를 띄우는 등의 작업에서 Application Context를 사용하는 경우, UI의 스타일이나 테마가 올바르게 적용되지 않을 수 있습니다. 특히, Activity의 생명 주기와 밀접한 UI 관련 작업에서는 ActivityContext를 사용해야 합니다.
  • 테마 및 스타일 적용이 필요한 경우:
    • ActivityApplication과 달리 특정 테마와 스타일을 가질 수 있습니다. ActivityContext를 사용하면 해당 테마와 스타일이 적용된 UI 요소를 생성할 수 있지만, Application Context를 사용하면 기본 테마가 적용될 수 있습니다. 예를 들어, 대화상자(AlertDialog)를 띄우는 경우, Application Context를 사용하면 기본 시스템 테마가 적용되므로 ActivityContext를 사용하는 것이 적절합니다.
  • 뷰 또는 UI 컴포넌트의 생성(=뷰의 생성 및 관리 작업):
    • View 또는 UI Component는 특정 ActivityFragment에 속해 있으므로, 이들을 생성하거나 관리할 때는 해당 Activity 또는 FragmentContext를 사용하는 것이 맞습니다. Application Context를 사용하면 뷰가 잘못된 컨텍스트에 바인딩되어 의도한 대로 동작하지 않을 수 있습니다.

 

Application Context의 DI(hilt) 설정

1. Application 단의 Context 주입

1.1. @HiltAndroidApp 주석 추가
Application 클래스를 Hilt로 설정합니다:

@HiltAndroidApp
class MyApp : Application() {
    // Application 단에서 필요한 설정들
}

 

1.2. Context 제공자 모듈 작성
Hilt 모듈을 통해 Application Context를 제공하도록 설정합니다:

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    @Singleton
    fun provideContext(@ApplicationContext context: Context): Context {
        return context
    }
}

 

2. 싱글톤 객체를 활용한 전역 Context 관리

클래스에서 Context를 주입받고 싶지 않다면,
다른 방법으로 Application 단의 Context를 전역적으로 관리하면서도 코드의 재사용성을 높일 수 있습니다.
이 경우, 전역적으로 사용할 수 있는 Context를 제공하는 싱글톤 객체를 만들어 확장 함수에서 활용할 수 있습니다.

전역적으로 Context를 관리하기 위해 싱글톤 패턴을 사용할 수 있습니다. 이 방법을 사용하면 Context를 직접 주입하지 않고도 쉽게 접근할 수 있습니다.

 

2.1. AppContextProvider 싱글톤 객체 생성

object AppContextProvider {
    lateinit var context: Context
        private set

    fun init(context: Context) {
        this.context = context
    }
}

AppContextProvider는 애플리케이션 시작 시 Context를 초기화하고, 그 이후에는 전역적으로 접근할 수 있도록 합니다.

 

2.2. Application 클래스에서 초기화

애플리케이션 클래스에서 AppContextProvider를 초기화합니다:

@HiltAndroidApp
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        AppContextProvider.init(this)
    }
}

 

2.3. Application Context 접근

이제 Context를 직접 주입받지 않고, 싱글톤 객체를 통해 전역적으로 접근할 수 있습니다:

AppContextProvider.context.resources.displayMetrics

 

 


 

고려사항

  1. 싱글톤 패턴의 신중한 사용:
    • 싱글톤 패턴을 사용하면 Context를 전역적으로 사용할 수 있어 편리하지만, 잘못 사용할 경우 여전히 메모리 누수 등의 문제가 발생할 수 있습니다. 특히, ActivityFragmentContext를 사용해야 하는 경우에는 이 방법을 사용하지 않는 것이 좋습니다.
  2. 유연성의 제한:
    • 전역적으로 ApplicationContext에만 접근할 수 있으므로, 특정 UI 요소와 관련된 Context가 필요한 경우에는 이 방법이 적절하지 않을 수 있습니다.
  3. 테스트 가능성:
    • 전역 싱글톤 객체를 사용하면 단위 테스트에서 Context를 모의하기가 어려워질 수 있습니다. 단위 테스트에서 이 싱글톤 객체를 사용하는 코드를 테스트하기 위해서는 추가적인 설정이 필요할 수 있습니다.

이 방법을 통해 DimensionConverter 클래스에서 Context를 직접 주입받지 않고도 확장 함수를 전역적으로 사용할 수 있습니다. 하지만 이 접근 방식이 모든 경우에 최선이 아닐 수 있으므로, 프로젝트의 요구 사항에 맞게 선택하는 것이 중요합니다.

반응형