dagger 2: di eficiente em android - tdc 2015
TRANSCRIPT
![Page 1: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/1.jpg)
Dagger 2Injeção de Dependência no Android
![Page 2: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/2.jpg)
rafaeltoledo.net
@_rafaeltoledo
Desenv. Android @ Concrete Solutions
![Page 3: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/3.jpg)
O que é Injeção de Dependência?
![Page 4: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/4.jpg)
“Injeção de Dependência (ou Dependency Injection, em inglês) é um padrão de desenvolvimento de programas de
computadores utilizado quando é necessário manter baixo o nível de acoplamento entre
diferentes módulos de um sistema. (...)”
![Page 5: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/5.jpg)
“Nesta solução as dependências entre os módulos não são definidas
programaticamente, mas sim pela configuração de uma infraestrutura de
software (container) que é responsável por "injetar" em cada componente suas
dependências declaradas. A Injeção de dependência se relaciona com o padrão Inversão de controle mas não pode ser
considerada um sinônimo deste.”
Wikipedia, 2015
![Page 6: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/6.jpg)
?????????
![Page 7: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/7.jpg)
Diz respeito a separação de onde os objetos são criados e onde são utilizados
![Page 8: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/8.jpg)
Em vez de criar, você pede
![Page 9: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/9.jpg)
class UserController {
void doLogic() {
try {
User user = RetrofitApi.getInstance().getUser(1);
new UserDaoImpl().save(user);
Logger.getForClass(UserController.class).log("Success");
} catch (IOException e) {
Logger.getForClass(UserController.class).logException(e);
}
}
}
![Page 10: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/10.jpg)
class UserController {
UserDaoImpl dao;
Logger logger;
UserApi api;
void doLogic() {
try {
api = RetrofitApi.getInstance();
User user = api.getUser(1);
dao = new UserDaoImpl();
dao.save(user);
logger = Logger.getForClass(UserController.class);
logger.log("Success");
} catch (IOException e) {
logger = Logger.getForClass(UserController.class);
logger.logException(e);
}
}
}
![Page 11: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/11.jpg)
class UserController {
UserDao dao; // Interface!
Logger logger;
Api api;
void doLogic() {
try {
if (api == null) api = RetrofitApi.getInstance();
User user = api.getUser(1);
if (dao == null) dao = new UserDaoImpl();
dao.save(user);
if (logger == null) logger = Logger.getForClass(UserController.class);
logger.log("Success");
} catch (IOException e) {
if (logger == null) logger = Logger.getForClass(UserController.class);
logger.logException(e);
}
}
}
![Page 12: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/12.jpg)
class UserController {
UserDao dao = new UserDaoImpl();
Logger logger = Logger.getForClass(UserController.class);
Api api = RetrofitApi.getInstance();
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) {
logger.logException(e);
}
}
}
![Page 13: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/13.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 14: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/14.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 15: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/15.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 16: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/16.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 17: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/17.jpg)
UserDao
UserController
![Page 18: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/18.jpg)
UserDao
UserController
SessionManager
![Page 19: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/19.jpg)
UserDao
UserController
SessionManagerSignInController
![Page 20: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/20.jpg)
UserDao
UserController
SessionManagerSignInController
CookieJob
JobManager
JobController
PermissionChecker
ReminderJob
RoleController
CandyShopper
FruitJuicerJob
UnknownController
![Page 21: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/21.jpg)
UserDao
UserController
SessionManagerSignInController
CookieJob
JobManager
JobController
PermissionChecker
ReminderJob
RoleController
CandyShopper
FruitJuicerJob
UnknownController
EM TODO LUGAR!
![Page 22: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/22.jpg)
class UserDaoImpl implements UserDao {
public UserDaoImpl() {
//...
}
}
![Page 23: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/23.jpg)
class UserDaoImpl implements UserDao {
public UserDaoImpl(Context context) {
//...
}
}
![Page 24: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/24.jpg)
![Page 25: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/25.jpg)
Alteração em todas as classes!
![Page 26: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/26.jpg)
Alteração em todas as classes!
Muito retrabalho!
![Page 27: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/27.jpg)
Alteração em todas as classes!
Muito retrabalho!
![Page 28: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/28.jpg)
Alteração em todas as classes!
Muito retrabalho!
![Page 29: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/29.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 30: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/30.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 31: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/31.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController(UserDao dao, Api api, Logger logger) {
this.dao = dao;
this.api = api;
this.logger = logger;
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 32: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/32.jpg)
DI: Separação do uso e criação de objetos
![Page 33: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/33.jpg)
DI: Separação do uso e criação de objetos
não há a necessidade de bibliotecasou frameworks!
![Page 34: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/34.jpg)
Desvantagem: muito boilerplate
![Page 35: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/35.jpg)
Spring, Guice, Dagger 1 & cia
#oldbutgold
![Page 36: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/36.jpg)
Spring, Guice, Dagger 1 & cia
#oldbutnot
![Page 37: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/37.jpg)
Dagger 2
![Page 38: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/38.jpg)
Dagger 2?
![Page 39: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/39.jpg)
Dagger 2
● Fork do Dagger, da Square, feito pela Google
● Elimina todo o uso de reflections
● Construída sobre as anotações javax.inject da especificação JSR-330
![Page 40: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/40.jpg)
Dagger 2
● Validação de todo o grafo de dependências em tempo de compilação
● Menos flexível, se comparado ao Dagger 1 - ex.: não possui module overriding
● Proguard configuration-free
![Page 41: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/41.jpg)
Dagger 2
● API enxuta!
● Código gerado é debugger-friendly
● Muito performático
● google.github.io/dagger
![Page 42: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/42.jpg)
public @interface Component {
Class<?>[] modules() default {};
Class<?>[] dependencies() default {};
}
public @interface Subcomponent {
Class<?>[] includes() default {};
}
public @interface Module {
Class<?>[] includes() default {};
}
public @interface Provides {
}
public @interface MapKey {
boolean unwrapValue() default true;
}
public interface Lazy<T> {
T get();
}
![Page 43: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/43.jpg)
// JSR-330
public @interface Inject {
}
public @interface Scope {
}
public @interface Qualifier {
}
![Page 44: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/44.jpg)
Como integro no meu projeto?
![Page 45: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/45.jpg)
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
allprojects {
repositories {
jcenter()
}
}
![Page 46: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/46.jpg)
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}
allprojects {
repositories {
jcenter()
}
}
![Page 47: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/47.jpg)
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.6'
}
}
allprojects {
repositories {
jcenter()
}
}
![Page 48: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/48.jpg)
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.6'
}
}
allprojects {
repositories {
jcenter()
}
}
![Page 49: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/49.jpg)
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
defaultConfig {
applicationId 'net.rafaeltoledo.tdc2015'
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:22.2.1'
}
![Page 50: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/50.jpg)
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
defaultConfig {
applicationId 'net.rafaeltoledo.tdc2015'
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.google.dagger:dagger:2.0.1'
apt 'com.google.dagger:dagger-compiler:2.0.1'
provided 'org.glassfish:javax.annotation:10.0-b28'
}
![Page 51: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/51.jpg)
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
defaultConfig {
applicationId 'net.rafaeltoledo.tdc2015'
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.google.dagger:dagger:2.0.1'
apt 'com.google.dagger:dagger-compiler:2.0.1'
provided 'org.glassfish:javax.annotation:10.0-b28' // JSR-330
}
![Page 52: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/52.jpg)
E pronto!
![Page 53: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/53.jpg)
Vamos começar?
![Page 54: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/54.jpg)
@Inject
@Component @Module
@Provides
Dagger 2
![Page 55: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/55.jpg)
@Inject
● Parte da JSR-330
● Marca quais dependências devem ser fornecidas pelo Dagger
● Pode aparecer de 3 formas no código
![Page 56: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/56.jpg)
public class TdcActivityPresenter {
private TdcActivity activity;
private TdcDataStore dataStore;
@Inject
public TdcActivityPresenter(TdcActivity activity,
TdcDataStore dataStore) {
this.activity = activity;
this.dataStore = dataStore;
}
}
1. No Construtor
![Page 57: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/57.jpg)
1. No Construtor
● Todas as dependências vem do grafo de dependências do Dagger
● Anotar uma classe dessa forma faz com que ela também faça parte do grafo de dependências (podendo ser injetada em outras classes)
![Page 58: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/58.jpg)
1. No Construtor
● Limitação: não podemos anotar mais que um construtor com a anotação @Inject
![Page 59: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/59.jpg)
public class TdcActivity extends AppCompatActivity {
@Inject TdcActivityPresenter presenter;
@Inject SharedPreferences preferences;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
getComponent().inject(this);
}
}
2. Nos Atributos da Classe
![Page 60: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/60.jpg)
2. Nos Atributos da Classe
● A injeção nesse caso deve ser manual, caso contrários os atributos serão todos nulos
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
getComponent().inject(this);
}
● Limitação: os atributos não podem ser privados!
![Page 61: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/61.jpg)
public class TdcActivityPresenter {
private TdcActivity activity;
@Inject
public TdcActivityPresenter(TdcActivity activity) {
this.activity = activity;
}
@Inject
public void enableAnalytics(AnalyticsManager analytics) {
analytics.track(this);
}
}
3. Em métodos públicos
![Page 62: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/62.jpg)
3. Em métodos públicos
● Utilizado em conjunto com a anotação no construtor da classe
● Para casos onde o objeto injetado necessitamos da instância da própria classe na dependência fornecida
@Inject
public void enableAnalytics(AnalyticsManager analytics) {
analytics.track(this);
}
![Page 63: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/63.jpg)
3. Em métodos públicos
● O método anotado é chamado automaticamente logo após o construtor
![Page 64: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/64.jpg)
@Module
● Parte da API do Dagger
● Utilizada para identificar classes que fornecem dependências
![Page 65: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/65.jpg)
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
}
![Page 66: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/66.jpg)
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
}
![Page 67: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/67.jpg)
@Provide
● Utilizada nas classes anotadas como @Module para identificar quais métodos retornam dependências
![Page 68: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/68.jpg)
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
}
![Page 69: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/69.jpg)
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
}
![Page 70: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/70.jpg)
@Component
● É a anotação que liga os @Modules aos @Injects
● É colocada em uma interface
● Define quais módulos possui, quem será injetado
![Page 71: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/71.jpg)
@Component
● Precisa especificar obrigatoriamente seu escopo (ciclo de vida de suas dependências)
● Pode publicar dependências
● Pode possuir outros componentes
![Page 72: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/72.jpg)
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
![Page 73: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/73.jpg)
@Singleton // Escopo
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
![Page 74: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/74.jpg)
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
![Page 75: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/75.jpg)
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity); // Caso queira encadear
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
![Page 76: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/76.jpg)
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager(); // Dependências visíveis
} // para outros componentes*
![Page 77: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/77.jpg)
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
![Page 78: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/78.jpg)
@ActivityScope // Escopo personalizado
@Component(
modules = TdcActivityModule.class,
dependencies = TdcComponent.class
)
public interface TdcActivityComponent {
TdcActivity inject(TdcActivity activity);
TdcActivityPresenter presenter();
}
![Page 79: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/79.jpg)
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerMainComponent implements MainComponent {
private Provider<ApiService> provideApiServiceProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MainComponent create() {
return builder().build();
}
private void initialize(final Builder builder) {
this.provideApiServiceProvider =
ScopedProvider.create(MainModule_ProvideApiServiceFactory.create(builder.mainModule));
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(
(MembersInjector) MembersInjectors.noOp(), provideApiServiceProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
}
![Page 80: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/80.jpg)
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
}
![Page 81: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/81.jpg)
public class TdcApp extends Application {
TdcAppComponent component;
@Override
public void onCreate() {
component = DaggerTdcAppComponent.create();
component = DaggerTdcAppComponent.builder()
.dataModule(new DataModule(this)) // Módulo com construtor
.build(); // parametrizado
}
}
Instanciando um Componente
![Page 82: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/82.jpg)
Dagger 2Escopos dinâmicos
![Page 83: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/83.jpg)
Escopo = ciclo de vida do grafo de dependências (componente)
![Page 84: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/84.jpg)
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
![Page 85: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/85.jpg)
@ActivityScope // Escopo personalizado
@Component(
modules = TdcActivityModule.class,
dependencies = TdcComponent.class
)
public interface TdcActivityComponent {
TdcActivity inject(TdcActivity activity);
TdcActivityPresenter presenter();
}
![Page 86: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/86.jpg)
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UserScope {
}
Definição de um escopo
![Page 87: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/87.jpg)
Exemplo de uso
Miroslaw Stanek frogermcs.github.io
![Page 88: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/88.jpg)
@Singleton
@Component(modules = DataModule.class)
public interface TdcAppComponent {
UserComponent plus(UserModule module);
// não é necessário expor as dependências
}
Implementação
![Page 89: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/89.jpg)
@UserScope
@Subcomponent(modules = UserModule.class)
public interface UserComponent {
UserActivityComponent plus(UserActivityModule module);
}
Implementação
![Page 90: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/90.jpg)
public class TdcApp extends Application {
TdcAppComponent component;
UserComponent userComponent;
public UserComponent createUserComponent(User user) {
userComponent = component.plus(new UserModule(user));
return userComponent;
}
public void releaseUserComponent() {
userComponent = null;
}
...
}
Implementação
![Page 91: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/91.jpg)
Dagger 2Outras coisas legais!
![Page 92: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/92.jpg)
@Inject
Lazy<SharedPreferences> prefs;
void salvar() {
prefs.get().edit().putString("status", "ok!").apply();
}
Dependências “Preguiçosas”
![Page 93: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/93.jpg)
// No módulo
@Provides @Singleton
@ApiUrl String provideApiUrl(Context context) {
return context.getString(R.string.api_url);
}
@Provides @Singleton
@AccessToken String provideRestAdapter(SharedPreferences prefs) {
return prefs.getString("token", null);
}
// Na classe a ser injetada
@Inject @AccessToken
String accessToken;
Qualificadores
![Page 94: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/94.jpg)
// Declarando sua anotação
@MapKey(unwrapValue = true)
@interface GroupKey {
String value();
}
@MapKey
![Page 95: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/95.jpg)
// Fornecendo dependências no módulo
@Provides(type = Type.MAP)
@GroupKey("um")
String provideFirstValue() {
return "primeiro valor";
}
@Provides(type = Type.MAP)
@GroupKey("dois")
String provideSecondValue() {
return "segundo valor";
}
@MapKey
![Page 96: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/96.jpg)
// Uso
@Inject
Map<String, String> map; // {um=primeiro valor, dois=segundo valor}
● Por enquanto, só aceita Map e Set, e valores do tipo String e Enumeradores
@MapKey
![Page 97: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/97.jpg)
Ok! Tudo muito bonito mas...
![Page 98: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/98.jpg)
O que eu ganho de fato com tudo isso?
![Page 99: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/99.jpg)
Grandes benefícios
● Código mais limpo e organizado
● Melhorias no gerenciamento de objetos (melhor controle de singletons)
● Código mais fácil de TESTAR
![Page 100: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/100.jpg)
Dagger 2 e Testes
● Programar orientado a interfaces - mocks
● Sobrescrita de Componentes e Módulos
![Page 101: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/101.jpg)
Dagger 2 e Testes
@Module
public class TestMainModule {
@Provides // Poderíamos fazer com o Retrofit Mock!
public ApiService provideApiService() {
return new ApiService() {
@Override
public List<Repo> listRepos() {
return Arrays.asList(
new Repo("my-test-repo"),
new Repo("another-test-repo")
);
}
};
}
}
![Page 102: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/102.jpg)
Dagger 2 e Testes
@Component(modules = DebugMainModule.class)
public interface TestMainComponent extends MainComponent {
}
![Page 103: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/103.jpg)
Dagger 2 e Espresso 2
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
// ...
@Before
public void setUp() {
Instrumentation instrumentation =
InstrumentationRegistry.getInstrumentation();
MainApplication app = (MainApplication)
instrumentation.getTargetContext().getApplicationContext();
app.setComponent(DaggerDebugMainComponent.create());
rule.launchActivity(new Intent());
}
}
![Page 104: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/104.jpg)
Dagger 2 e Robolectric 3
@RunWith(RobolectricGradleTestRunner.class)
@Config(sdk = 21, constants = BuildConfig.class)
public class MainActivityTest {
// ...
@Before
public void setUp() {
MainComponent component = DaggerDebugMainComponent.create();
MainApplication app =
((MainApplication) RuntimeEnvironment.application)
.setComponent(component);
}
}
![Page 105: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/105.jpg)
Dagger 2github.com/rafaeltoledo/dagger2-tdc2015
![Page 106: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/106.jpg)
Para saber mais
● Site oficial - google.github.io/dagger
● Dagger 2 - A New Type of Dependency Injection (Gregory Kick) - vai.la/fdwt
● The Future of Dependency Injection with Dagger 2 (Jake Wharton) - vai.la/fdwy
● froger_mcs Dev Blog - frogermcs.github.io
![Page 107: Dagger 2: DI eficiente em Android - TDC 2015](https://reader031.vdocuments.net/reader031/viewer/2022013108/55caf7e8bb61eb9a2b8b4607/html5/thumbnails/107.jpg)
OBRIGADO!
rafaeltoledo.net
@_rafaeltoledo
Desenv. Android @ Concrete Solutionsestamos contratando!
concretesolutions.com.br/carreira