본문
170609(금) - DI with Dagger2
DI with Dagger2
http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
Scope
- Singleton은 API client, database helpers, analytics managers 등에 쓰인다.
- 그러나 DI를 사용한다면 이런식으로 객체를 직접 가져오면 안됨.
- @Inject가 알아서 객체를 잘 가져와 준다.
- Dagger2는 가능한 scope까지 instance를 유지시켜 준다.
ex)
- @ApplicationScope
Application object만큼 오래 살아 남는다.
- @ActivityScope
Activity가 존재하는 한 reference 유지
- CustomScope
그러나 기본적으로 Dagger2에 위와같은 annotation은 없음.
@Singleton 이 기본적으로 제공
Scope ex
- @Singleton
application scope
실제로는 Application 만큼 오래 live한다.
- @UserScope
logging 된 user 와 연관된 class instance scope
- @ActivityScope
Activity 동안 live 하는 instance scope (ex : presenter)

Scopes lifecycle
Implementation
- Implement proper configuration of component.
- 2 ways
1. @Subcomponent 사용
- object graph 전체에 access 가능
2. Component dependencies
- component interface에 노출된 object에만 access 가능
- AppComponent의 Subcomponent인 Usercomponent와 SplashActivityComponent는 AppModule, GithubApiModule에서 생성된 instance에 access 가능
@Singleton
@Component(
modules = {
AppModule.class,
GithubApiModule.class
}
)
public interface AppComponent {
UserComponent plus(UserModule userModule);
SplashActivityComponent plus(SplashActivityModule splashActivityModule);
}- UserComponent는 plus()의 parameter로 전달되는 다른 module을 필요로 한다.
- AppComponent의 graph는 extending 된다.
- AppComponent에서 extend 된 UserComponent에서 가져온 instance는 Singleton 범위이지만,
- UserComponent의 일부인 UserModule에서 생성되는 component는 UserComponent instance 만큼 지속되는 local singleton.
- UserComponent appComponent = appComponent.plus(new UserModule(user)) (UserComponent instance 생성) 마다 UserModule에서 가져오는 object는 다른 instance 이다.
@UserScope
@Subcomponent(
modules = {
UserModule.class
}
)
public interface UserComponent {
RepositoriesListActivityComponent plus(RepositoriesListActivityModule repositoriesListActivityModule);
RepositoryDetailsActivityComponent plus(RepositoryDetailsActivityModule repositoryDetailsActivityModule);
}- Annotation create
@Scope @Retention(RetentionPolicy.RUNTIME) // ??? public @interface UserScope { }
- UserComponent의 lifecycle을 담당해야만 한다.
- initialization과 release를 신경써야 한다.
public class GithubClientApplication extends Application {
private AppComponent appComponent;
private UserComponent userComponent;
//...
public UserComponent createUserComponent(User user) {
userComponent = appComponent.plus(new UserModule(user));
return userComponent;
}
public void releaseUserComponent() {
userComponent = null;
}
//...
}Under the hood
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class UserModule_ProvideRepositoriesManagerFactory implements Factory<RepositoriesManager> {
//...
@Override
public RepositoriesManager get() {
RepositoriesManager provided = module.provideRepositoriesManager(userProvider.get(), githubApiServiceProvider.get());
if (provided == null) {
throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
}
return provided;
}
public static Factory<RepositoriesManager> create(UserModule module, Provider<User> userProvider, Provider<GithubApiService> githubApiServiceProvider) {
return new UserModule_ProvideRepositoriesManagerFactory(module, userProvider, githubApiServiceProvider);
}
}private final class UserComponentImpl implements UserComponent {
//...
private UserComponentImpl(UserModule userModule) {
if (userModule == null) {
throw new NullPointerException();
}
this.userModule = userModule;
initialize();
}
private void initialize() {
this.provideUserProvider = ScopedProvider.create(UserModule_ProvideUserFactory.create(userModule));
this.provideRepositoriesManagerProvider = ScopedProvider.create(UserModule_ProvideRepositoriesManagerFactory.create(userModule, provideUserProvider, DaggerAppComponent.this.provideGithubApiServiceProvider));
}
//...
}- factory에서 instance를 가져와서 singleton 처럼 저장
- 따라서 single instance를 반환 가능
public final class ScopedProvider<T> implements Provider<T> {
//...
private ScopedProvider(Factory<T> factory) {
assert factory != null;
this.factory = factory;
}
@SuppressWarnings("unchecked") // cast only happens when result comes from the factory
@Override
public T get() {
// double-check idiom from EJ2: Item 71
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
instance = result = factory.get();
}
}
}
return (T) result;
}
//...
}'Mobile > DI' 카테고리의 다른 글
| 170712(수) - Dependency Injection with Dagger2 (0) | 2017.07.12 |
|---|---|
| 170707(금) - android-architecture-todo-mvp-dagger (0) | 2017.07.07 |
| 170609(금) - DI with Dagger2 (0) | 2017.06.09 |
| 170609 (금) - DI with Dagger2 (0) | 2017.06.09 |
| 170608(목) - DI with Dagger2 (0) | 2017.06.08 |
댓글