오늘도 더 나은 코드를 작성하였습니까?

Android app에서 Dagger 사용 본문

DI/Dagger2

Android app에서 Dagger 사용

hik14 2021. 5. 3. 18:32

권장사항

 

- @Inject 와 함께 생성자 삽입을 사용하여 Dagger 그래프에 유형을 추가한다. 

가능하지 않다면, @Bind를 이용하여 인터페이스에 어떤 구현이 있어야 하는지 Dagger에 알려줌.

@Provides를 사용하여 프로젝트가 소유하지 않은 클래스를 제공하는 방법을 Dagger에 알려줌.

 

- 구성요소에서 모듈을 한 번만 선언 한다. 

 

- 사용되는 전체 기간에 따라 범위 주석의 이름을 설정한다. (@ApplicationScope, @LoggedUserScope, @AcitivityScope)

 

 

Android에서 Dagger 사용

Android에서 개발자는 앱이 실행되는 동안 그래프 인스턴스가 메모리에 있기를 원하기 때문에 일반적으로 애플리케이션 클래스 내부에 Dagger 그래프를 만듭니다. 이렇게 하면 그래프는 앱 수명 주기에 연결됩니다.

 

경우에 따라 애플리케이션 컨텍스트를 그래프에서 사용하려고 할 수도 있습니다. 이를 위해서는 그래프가 애플리케이션 클래스 내에 있어야 합니다.

 

한 가지 이점은 다른 Android 프레임워크 클래스에서도 그래프를 사용할 수 있다는 것입니다.

테스트에서 맞춤 애플리케이션 클래스를 사용할 수 있도록 하여 테스트를 단순화합니다

 

@Component로 주석이 지정된 인터페이스는 그래프를 생성하기 때문에, ApplicationComponent 또는 ApplicationGraph로 호출할 수있다.  커스텀 Application 클래스에 그 구성요소의 인스턴스를 유지하고 애플리케이션 그래프가 필요할 때마다 인스턴스를 호출합니다.

// the Application graph 정의.
@Component
interface ApplicationComponent { ... }

// appComponent는 앱 전체 생명주기를 공유하며 메모리에 존재한다. 
class MyApplication: Application() {
    // 전체 앱에서 사용되는 애플리케이션 그래프에 대한 참조
    val appComponent = DaggerApplicationComponent.create()
}

 

Activity / Fragment와 같은 특정 Android 프레임워크 클래스는 OS에 의해 객체화되기 때문에 Dagger가 자동생성해 줄 수없다.

즉, 생성자 삽입이 아닌 필드 삽입을 이용한다. 

class LoginActivity: Activity() {
    // Dagger가 그래프에서 LoginViewModel의 인스턴스를 제공하기를 원합니다.
    @Inject lateinit var loginViewModel: LoginViewModel
}

(여기서 뷰모델은 android 아키텍쳐의 구성요소가 아니라 일반 클래스이다.)

 

Activity에  종속성 항목 삽입

Dagger는 ViewModel을 제공하기 위해 LoginActivity가 Graph에 액세스해야 한다는 것을 알아야 한다. 

@Component 인터페이스를 사용하여 그래프에서 가져오려는 객체의 반환 하는 함수를 노출함으로써 그래프에서 객체를 가져온다.

 

이 경우 종속 항목을 삽입받아야 하는  객체(LoginActivity)에 관해 Dagger에 알려주어야 한다. 

이를 위해 삽입을 요청하는 객체를 매개변수로 사용하는 함수를 노출합니다.

@Component
interface ApplicationComponent {
    // Dagger에게 LoginActivity가 주입을 받아야 한다고 알려주어야 한다. 
    // 그래프는 LoginActivity가 필요로 하는 필드의 의존성을 제공할 해야 하기 때문이다. 
    fun inject(activity: LoginActivity)
}

위의 inject 함수는 LoginActivity가 graph에 접근 하여 주입받기를 원한다고 Dagger에 알린다. 

 Dagger는 LoginActivity에 필요한 모든 종속 항목(LoginViewModel 또한 종속항목을 가지고 있다.)을 충족해야 한다.

 

삽입을 요청하는 클래스가 여러 개 있다면 구성요소의 모든 클래스를 정확한 유형으로 명시적으로 선언해야 한다.

예를 들어 삽입을 요청하는 LoginActivity 와 RegistrationActivity가 있다면 두 경우를 모두 포괄하는 일반 메서드 하나를 호출하는 대신 두 개의 inject() 메서드를 만들어야 한다.  inject() 메서드는 제공해야 할 항목을 Dagger에 알리지 않습니다.

인터페이스(ApplicationComponent)안의 함수는 임의의 이름을 가질 수 있지만, 매개변수로 삽입할 객체를 수신할 때 inject()로 호출하는 것은 Dagger의 규칙이다. 

 

Activity에 객체를 주입하기 위해서는 Application class 내에 정의된 appComponent를 사용하며, 주입을 받아야 할 Activity를 매개변수로 넘겨 주어 Injection()을 호출한다. 

 

Activity에 객체를 주입할때 Fragment 복원과 관련되 문제를 방지하기 위해 Super.onCreate()를 호출하기전 onCreate()메소드에 Dagger를 삽입한다.( Super.onCreate()의 복원단계에서 Activity에 Binding되는 Fragement를 연결한다.)

 

Fragment에 객체를 주입할때 onAttach()에서 Dagger를 주입한다. Super.onAttach()가 호출되기 전에 되어야 한다.

class LoginActivity: Activity() {
    // 그래프로 부터 Dagger가 LoginViewModel을 제공하는 것을 받는 필드. 
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        //Dagger가 @Inject 주석이 붙은 변수를 초기화 시킨다. 
        (applicationContext as MyApplication).appComponent.inject(this)
       
        // 이후 loginViewModel는 변수를 사용가능하다. 
        super.onCreate(savedInstanceState)
    }
}

// @Inject는 Dagger에게 어떻게 LoginViewModel을 생성하는지 알려준다. 
class LoginViewModel @Inject constructor(
    private val userRepository: UserRepository
) { ... }

 

Dagger에게 그래프를 작성하기 위해 나머지 종속성을 제공하는 방법을 알려주자!

class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }

class UserLocalDataSource @Inject constructor() { ... }
class UserRemoteDataSource @Inject constructor(
    private val loginService: LoginRetrofitService
) { ... }

Dagger modules

retrofit을 사용한다고 할때, UserRemoteDataSource는 LoginRetrofitService에 의존성을 가진다.

LoginRetrofitService 객체를 생성하는 방법은 지금까지 만들던것과는 조금 다르다. 생성자를 통한 객체를 생성하는 방식이 아닌. Builder()를 통해 매개변수를 전달하여 생성한다. 

 

@inject 주석과 별도로, Dagger에게 클래스의 인스턴스를 주입하는 방법을 알려주는 방법이 있다. 

그것은 모듈이며 하나의 클래스로 @Module 애노테이션이 추가된다. 

모듈 클래스 내부에서, @Provides 주석으로 종속성(주입될 것을)을 정의 할 수 있습니다.

@Module
class NetworkModule {
    // @Provides는 Dagger에게 어떻게 주입할 타입의 객체를 생성하는지 함수의 반환값을 통해 알려준다.
    // 주입할 타입의 객체를 생성하기 위해 또 다른 의존성이 필요할 경우 함수 parameter로 제공한다. 
    @Provides
    fun provideLoginRetrofitService(): LoginRetrofitService {
        // Dagger가 LoginRetrofitService을 주입할때 마다 이 함수가 호출된다. 
        return Retrofit.Builder()
                .baseUrl("https://example.com")
                .build()
                .create(LoginService::class.java)
    }
}

@module 클래스는 객체를 제공하는 방법에 대한 정보를 의미적으로 캡슐화한 클래스이다. 

@Provides 메서드의 종속성은 해당 메서드의 매개 변수이며 반환 값은 주입할 객체이다. 

LoginRetrofitService는 다른 의존성이 없기 때문에 파라미터를 받을 필요가 없다. 

 

OkHttpClient를 매개 변수로 선언 한 경우 Dagger는 LoginRetrofitService의 종속성을 충족하기 위해 그래프에서 OkHttpClient 인스턴스를 제공해야합니다.

@Module
class NetworkModule {
    // Hypothetical dependency on LoginRetrofitService
    @Provides
    fun provideLoginRetrofitService(
        okHttpClient: OkHttpClient
    ): LoginRetrofitService { ... }
}

 

Dagger의 종속성 그래프가 이렇게 생성한 모듈(주입방법)을 알기 위해서는 @Component 인터페이스에 모듈을 알려주어야 한다. 

// @Component의 인자로 모듈 클래스를 넣어 주어서, 종속성 그래프를 생성시 모듈을 포함시킨다. 
@Component(modules = [NetworkModule::class])
interface ApplicationComponent {
    ...
}

 

 

Dagger 그래프에 주입할 타입의 객체를 추가하는 권장 방법은 생성자 주입 (즉, 클래스 생성자에 @Inject 주석 사용)을 사용하는 것입니다.

만약 생성자 주입이 불가능하다면, Dagger의 module을 통해 주입하는 것이다. Dagger에서 연산과 그 결과에 따라 주입할 객체의 인스턴스를 만드는 방법을 결정하려는 경우입니다

그래프의 진입 점은 LoginActivity입니다.

LoginActivity는 LoginViewModel을 주입하기 때문에 Dagger는 LoginViewModel의 인스턴스를 제공하는 방법을 알고있는 그래프를 생성한다. 재귀적으로 LoginViewModel이 또 다른 의존성을 필요로한다면, @Injection으로 재귀적인 의존성을 파악할 수 있다.

 

Dagger에 의해 생성 된 ApplicationComponent 내부에는 제공하는 방법을 알고있는 모든 클래스의 인스턴스를 가져 오는 팩토리 유형 메소드가 있습니다. 위에서는 Dagger는 ApplicationComponent에 포함된 NetworkModule에 위임하여 LoginRetrofitService의 인스턴스를 가져옵니다.

 

Dagger scopes

범위는 component 에서 특정 타입의 고유한 인스턴스를 갖는 방법,  특정 타입 사용 범위를 component의 수명주기에 대한 지정하는 것입니다.

 

앱의 내부에서 UserRepository를 서로 다른 부분에서 사용하면서 사용할때 마다 새로운 객체를 만들지 않기 위해서, 앱 전체에서 사용할 수 있는 유일한 객체로 만들어야한다. 지속적으로 새로운 객체를 생성하는데 비용(메모리, CPU)등이 많이 소모되어, 고유한 객체를 다시 사용해야된다.  

 

LoginRetrofitService : 생성시 비용이 많이들 수 있으며 해당 개체의 고유 한 인스턴스를 재사용 할 수도 있습니다.

UserRemoteDataSource : 생성시 비용이 많이 들지 않으므로 구성 요소의 수명 주기로 범위를 지정할 필요가 없습니다.

 

@Singleton은 javax.inject 패키지와 함께 제공되는 유일한 범위 주석입니다. 이를 사용하여 ApplicationComponent 및 전체 애플리케이션에서 재사용하려는 객체를 지정할 수 있다. 

 

@Singleton
@Component(modules = [NetworkModule::class])
interface ApplicationComponent {
    fun inject(activity: LoginActivity)
}


@Singleton
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }


@Module
class NetworkModule {
    // Way to scope types inside a Dagger Module
    @Singleton
    @Provides
    fun provideLoginRetrofitService(): LoginRetrofitService { ... }
}

 

*범위 주석을 사용하는 Module 은 동일한 범위로 주석이 추가 된 components 에서만 사용할 수 있습니다.

즉, 위에 NetworkModule의  provideLoginRetrofitService @Singleton 이 붙었으면,  이 모듈을 사용하는 ComponentApplicationComponent 또한 @Singleton가 붙어야된다는 것이다.

 

scope 사용시 메모리 누수에 조심해야되며, scope가 지정된 components가 메모리에있는 한 생성된 객체도 메모리에 있습니다.

 

ApplicationComponent는 앱이 시작될 때 생성되기 때문에 (Application 클래스에서) 앱이 파괴되면 파괴됩니다. 따라서 UserRepository의 고유 인스턴스는 응용 프로그램이 파괴 될 때까지 항상 메모리에 남아 있습니다.

Dagger subcomponents

로그인 흐름(LoginActivity에 의해 관리)이 여러 fragment으로 구성된 경우 모든 fragment에서 동일한 LoginViewModel 인스턴스를 재사용해야한다. 하지만  @Singleton 범위를 달아서는 안된다. 그 이유는.

 

1.  LoginViewModel는 login flow가 끝난뒤에도 메모리에 남아있다.

2. 각각 login flow 에 대해 다른 LoginViewModel 인스턴스가 필요합니다.

예) 사용자가 로그 아웃하면 사용자가 처음 로그인했을 때와 동일한 인스턴스가 아닌 다른 LoginViewModel 인스턴스가 생성되야한다.

 

LoginViewModel의 범위를 LoginActivity의 수명 주기로 지정하려면  login flow 및 새로운 flow 에 대한 새로운 components (새 하위 그래프)를 생성한다.

 

@Component
interface LoginComponent {}

LoginActivity는 LoginComponent를 생성했기 때문에  LoginComponent에서 주입을 가져와야합니다.

 ApplicationComponent 클래스에서 LoginActivity를 주입하는 책임을 삭제해야 된다. 

@Component
interface LoginComponent {
    fun inject(activity: LoginActivity)
}

LoginViewModel은 UserRepository에 종속되기 때문에 LoginComponent는 ApplicationComponent에서 개체에 액세스 할 수 있어야 한다. LoginComponentApplicationComponent의 일부를 사용하도록 Dagger에 알리는 방법은 Dagger subcomponents를 사용해야 한다. 새 Component(LoginComponent)는 공유 리소스(UserRepository)를 포함하는 ApplicationComponent의 하위 구성 요소 여야합니다.

 

subcomponents의 인스턴스를 만들려면 parentcomponent의 인스턴스가 필요합니다.

따라서 parentcomponent에서 subcomponents에 제공하는 객체는 여전히 parentcomponent로 Scope가 지정됩니다.

 

LoginComponent를 ApplicationComponent의 하위 구성 요소로 정의해야합니다.  LoginComponent에 @Subcomponent 주석을 추가

 

@Subcomponent
interface LoginComponent {
    //이것은 Dagger에게 LoginActivity가 LoginComponent에서 주입을 요청하고
    //하위 구성요소 그래프는 LoginActivity가 주입하는 필드의 모든 종속성을 충족하여 주입한다.     
    fun inject(loginActivity: LoginActivity)
}

ApplicationComponent가 LoginComponent의 인스턴스를 만드는 방법을 알 수 있도록

LoginComponent 내에 subcomponent factory를 정의해야합니다.

@Subcomponent
interface LoginComponent {

    // Factory that is used to create instances of this subcomponent
    @Subcomponent.Factory
    interface Factory {
        fun create(): LoginComponent
    }

    fun inject(loginActivity: LoginActivity)
}

 

Dagger에게 LoginComponent가 ApplicationComponent의 하위 구성 요소임을 알리기

 

1. @Module 애노테이션에 인자로써 subcomponent 클래스를 전달하는 새로운 Dagger 모듈 (SubcomponentsModule)을 만듭니다

// @Module 주석의 "subcomponents"속성은 Dagger에게 
// LoginComponent는 SubcomponentsModule이 포함된 Components의 자식이된다.
// 즉, 이 모듈을 인자로 받는 다른 @Component 클래스가 있다면 LoginComponent는 자식이 된다. 
@Module(subcomponents = LoginComponent::class)
class SubcomponentsModule {}

 

2. ApplicationComponent에 위에서 생성한 모듈을 추가한다. 

@Singleton
@Component(modules = [NetworkModule::class, SubcomponentsModule::class])
interface ApplicationComponent {
}

LoginActivity를 주입을 해야하는 역활이 LoginComponent에 속하기 때문에 ApplicationComponent는 더 이상 LoginActivity에 주입 할 필요가 없습니다. 따라서 ApplicationComponent에서 inject () 메서드를 제거 한다.

 

하지만, ApplicationComponent를 사용하여 LoginComponent의 인스턴스를 만드는 방법을 알아야합니다.

ApplicationComponent는  ApplicationComponent의 인스턴스에서 LoginComponent의 인스턴스를 만들 수 있도록 인터페이스에 메서드를 추가한다,

 

3. ApplicationComponent 인터페이스에서 LoginComponent의 인스턴스를 생성하는 팩토리를 제공

@Singleton
@Component(modules = [NetworkModule::class, SubcomponentsModule::class])
interface ApplicationComponent {
// 이 팩토리 메소드를 통해서 LoginComponent를 생성할 수 있다. 
fun loginComponent(): LoginComponent.Factory
}

 

Subcomponent에 Scope 할당하기

프로젝트를 빌드할 때 ApplicationComponent 및 LoginComponent의 인스턴스를 모두 만들 수 있습니다.

App이 메모리에 있는 한 동일한 그래프 인스턴스를 사용하려고하기 때문에 ApplicationComponent가 App의 수명주기에 연결됩니다.

 

LoginComponent의 수명주기는 어떻게 될까?

LoginComponent가 필요한 이유 중 하나는 로그인 관련 Fragment간에 동일한 LoginViewModel 인스턴스를 공유해야하기 때문입니다.

또한,  새 login flow 가있을 때마다 다른 LoginViewModel 인스턴스를 생성해야한다.

 

LoginActivity의 생명주기는 LoginComponent의 올바른 수명를 알려준다.

새로운 LoginActivity를 생성하면 LoginComponent의 새 객체(loginComponet)와 객체(loginComponet)를 사용할 수있는 Fragment를 생성한다. 

 

LoginComponent가 LoginActivity 생명주기에 첨부되기 때문에, Application 클래스에서 applicationComponent에 대한 참조를 유지 한 것과 동일한 방식으로 LoginActivity가 LoginComponent에 대한 참조를 유지한다. 

class LoginActivity: Activity() {
    // login Graph에 대한 참조 
    lateinit var loginComponent: LoginComponent
    ...
}

변수 loginComponent는 Dagger에서 제공 할 변수를 기대하지 않기 때문에 @Inject로 주석 처리되지 않습니다.

 

ApplicationComponent를 사용하여 LoginComponent에 대한 참조를 가져온 아래과 같이 LoginActivity에 제공할 수있다. 

class LoginActivity: Activity() {
    // 로그인 그래프 참조.
    lateinit var loginComponent: LoginComponent

    // 로그인 그래프에 의해 주입될 대상 참조
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        // 애플리케이션 그래프를 이용해서 로그인 그래프를 생성한다. 
        loginComponent = (applicationContext as MyDaggerApplication)
                            .appComponent.loginComponent().create()

        // Dagger가 loginComponent(graph)에서 @Inject달린 필드를 초기화 한다. 
        loginComponent.inject(this)

        // 뷰모델을 사용가능하다. 
        super.onCreate(savedInstanceState)
    }
}

LoginComponent는 활동의 onCreate () 메서드에서 생성되며 activity가 소멸되면 으로 소멸됩니다.

 

LoginComponent는 공급 될 때마다 항상 동일한 LoginViewModel 인스턴스를 제공해야합니다. 사용자 지정 주석 범위를 만들고 LoginComponent 및 LoginViewModel에 주석을 추가하여 할 수 있다.

 

*주의사항

 

1. 객체 타입이 Scope 주석으로 표시되면 동일한 Scope로 주석이 달린 Component에서만 사용할 수 있습니다.

 

2. ComponentScope 주석으로 표시되면 해당 주석이있는 타입 또는 주석이 아예 없는 타입만 제공 할 수 있습니다.

 

3. SubComponent는 Parent Component 중 하나에서 사용하는 Scope 주석을 사용할 수 없습니다.

 

Scope를 @LoginScope라고 할 수 있지만 좋은 방법은 아닙니다.  Scope 주석의 이름은 수행하는 목적을 명시 적으로 나타내서는 안된다.

RegistrationComponent 및 SettingsComponent와 같은 siblingComponents 에서 주석을 재사용 할 수 있으므로 수명에 따라 이름을 지정해야합니다.

 

@LoginScope(수행 목적)대신 @ActivityScope(수명)로 사용한다.

// Activity Scope를 정의한다. 
@Scope
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ActivityScope

// @ActivityScope로 주석이 달린 클래스는 해당 그래프로 범위가 지정되며 Type이 공급할때
// 해당 유형의 동일한 인스턴스가 제공됩니다.
@ActivityScope
@Subcomponent
interface LoginComponent { ... }

// LoginViewModel의 고유한 인스턴스는 @ActivityScope 주석이 달린 구성 요소에 제공됩니다.
@ActivityScope
class LoginViewModel @Inject constructor(
    private val userRepository: UserRepository
) { ... }

LoginViewModel이 필요한 두 개의 프래그먼트가 있다면 둘 다 동일한 인스턴스로 제공된다.

예를 들어, LoginUsernameFragment 및 LoginPasswordFragment가있는 경우 LoginComponent에 의해 주입된다.

 

@ActivityScope
@Subcomponent
interface LoginComponent {

    @Subcomponent.Factory
    interface Factory {
        fun create(): LoginComponent
    }

    // All LoginActivity, LoginUsernameFragment and LoginPasswordFragment
    // request injection from LoginComponent. The graph needs to satisfy
    // all the dependencies of the fields those classes are injecting
    fun inject(loginActivity: LoginActivity)
    fun inject(usernameFragment: LoginUsernameFragment)
    fun inject(passwordFragment: LoginPasswordFragment)
}

 

component는 LoginActivity 객체에있는 component의 인스턴스에 액세스합니다. LoginUserNameFragment의 예제 코드는 다음 코드 조각에 나와 있습니다.

class LoginUsernameFragment: Fragment() {

    // 로그인그래프로 부터 제공받을 객체
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onAttach(context: Context) {
        super.onAttach(context)

        // LoginActivity로 부터 그래프를 얻어 @Inject 주석이 붙은 필드 객체 초기화
        (activity as LoginActivity).loginComponent.inject(this)

        // Now you can access loginViewModel here and onCreateView too
        // 뷰모델에 접근 가능하며 onCreateView에서도 접근가능함
      	// Activity와 연관 Fragment에서 동일한 객체 공유한다. 
    }
}
class LoginPasswordFragment: Fragment() {

    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onAttach(context: Context) {
        super.onAttach(context)

        (activity as LoginActivity).loginComponent.inject(this)

    }
}

 

Dagger 그래프가 새로운 SubComponent 추가된지 보여준다. 

그래프 분석.

 

1.  NetworkModule (LoginRetrofitService)은 @Component(modules = [NetworkModule::class, SubcomponentsModule::class])에서 지정 했으므로 ApplicationComponent에 포함됩니다.

 

2. UserRepository는 ApplicationComponent로 범위가 지정되어 있으므로 ApplicationComponent에 남아 있습니다.

프로젝트가 커지면 여러 기능간에 동일한 인스턴스를 공유하려고합니다.

 

3. LoginViewModel은 LoginComponent에 의해 주입 된 클래스에서만 필요하기 때문에 LoginComponent에 포함됩니다. ApplicationComponent의 종속성에는 LoginViewModel이 필요하지 않으므로 LoginViewModel은 ApplicationComponent에 포함되지 않습니다.

 

UserRepository를 ApplicationComponent로 Scope로 지정하지 않은 경우,  Dagger는 현재 UserRepository가 주입되는 유일한 위치인LoginComponent의 일부로 UserRepository 및 해당 종속성을 자동으로 포함시킨다.

 

서로 다른 생명주기에 객체의 범위를 지정하는것 외에도, subcomponents를 생성하는것은 App의 다른 부분을 서로 캡슐화하는 좋은 방법입니다.

 

앱의 Flow에 따라 다른 Dagger subcomponents 그래프를 생성하도록 앱을 구조화하면 메모리 및 시작 시간 측면에서보다 성능이 뛰어나고 확장 가능한 애플리케이션을 만드는 데 도움이됩니다.

 

Dagger 그래프를 만들 때 모범적인 방법

components 를 만들 때 해당 components 의 수명을 담당하는 요소를 고려해야한다.

예제의 경우 Application 클래스는 ApplicationComponent를 담당하고 LoginActivity는 LoginComponent를 담당합니다.

 

의미가있을 때만 범위 지정을 사용하십시오

범위 지정을 과도하게 사용하면 앱의 런타임 성능에 부정적인 영향을 미칠 수 있습니다.

 

component가 메모리에 있는한 주입된 객체는 메모리에 있고 Scope 지정된 개체(동일한 객체)를 가져 오는 데 더 많은 비용이 듭니다.

Dagger가 객체를 제공 할 때 팩토리 유형 공급자 대신 DoubleCheck 잠금을 사용합니다

즉, 새로 생성하는것 보다 기존의 객체를 범위 지정으로 가지고 오는 것이 더 많은 비용을 소모한다. 

'DI > Dagger2' 카테고리의 다른 글

Android Code Lab(Dagger2) 정리2  (0) 2021.12.21
Android Code Lab(Dagger2) 정리1  (0) 2021.12.20
Dagger Basic  (0) 2020.11.30
수동 종속성 삽입  (0) 2020.11.30
Android의 종속 항목 삽입  (0) 2020.11.24