Dagger 2.x Kılavuzu (Revize Edilmiş Baskı 6) :
Adımlar şu şekildedir:
1.) eklemek Dagger
için için build.gradle
dosyaları:
.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //added apt for source code generation
}
}
allprojects {
repositories {
jcenter()
}
}
- uygulama düzeyinde build.gradle :
.
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' //needed for source code generation
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
applicationId "your.app.id"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
apt 'com.google.dagger:dagger-compiler:2.7' //needed for source code generation
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.google.dagger:dagger:2.7' //dagger itself
provided 'org.glassfish:javax.annotation:10.0-b28' //needed to resolve compilation errors, thanks to tutplus.org for finding the dependency
}
2.)AppContextModule
Bağımlılıkları sağlayan sınıfınızı oluşturun .
@Module //a module could also include other modules
public class AppContextModule {
private final CustomApplication application;
public AppContextModule(CustomApplication application) {
this.application = application;
}
@Provides
public CustomApplication application() {
return this.application;
}
@Provides
public Context applicationContext() {
return this.application;
}
@Provides
public LocationManager locationService(Context context) {
return (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}
}
3.)AppContextComponent
enjekte edilebilir sınıfları almak için arayüz sağlayan sınıfı oluşturun .
public interface AppContextComponent {
CustomApplication application(); //provision method
Context applicationContext(); //provision method
LocationManager locationManager(); //provision method
}
3.1.) Bir uygulama ile bir modülü nasıl yaratırsınız:
@Module //this is to show that you can include modules to one another
public class AnotherModule {
@Provides
@Singleton
public AnotherClass anotherClass() {
return new AnotherClassImpl();
}
}
@Module(includes=AnotherModule.class) //this is to show that you can include modules to one another
public class OtherModule {
@Provides
@Singleton
public OtherClass otherClass(AnotherClass anotherClass) {
return new OtherClassImpl(anotherClass);
}
}
public interface AnotherComponent {
AnotherClass anotherClass();
}
public interface OtherComponent extends AnotherComponent {
OtherClass otherClass();
}
@Component(modules={OtherModule.class})
@Singleton
public interface ApplicationComponent extends OtherComponent {
void inject(MainActivity mainActivity);
}
Dikkat:: Oluşturulan bileşenin içinde kapsamlı bir sağlayıcı elde etmek için modülün açıklamalı yönteminde @Scope
ek açıklama ( @Singleton
veya gibi @ActivityScope
) sağlamanız gerekir @Provides
, aksi takdirde kapsamı kaldırılır ve her enjekte ettiğinizde yeni bir örnek alırsınız.
3.2.) Ne enjekte edebileceğinizi belirten Uygulama kapsamlı bir bileşen oluşturun (bu, injects={MainActivity.class}
Dagger 1.x'teki ile aynıdır ):
@Singleton
@Component(module={AppContextModule.class}) //this is where you would add additional modules, and a dependency if you want to subscope
public interface ApplicationComponent extends AppContextComponent { //extend to have the provision methods
void inject(MainActivity mainActivity);
}
3.3.) Bunu bağımlılıkları için olabilir bir yapıcı aracılığıyla kendiniz oluşturup Kullanarak yeniden tanımlamak istemeyeceksiniz@Module
, sen kullanabilirsiniz) örneğin, bunun yerine inşa tatlar kullanın (uygulama türünü değiştirmek için @Inject
açıklamalı yapıcısı.
public class Something {
OtherThing otherThing;
@Inject
public Something(OtherThing otherThing) {
this.otherThing = otherThing;
}
}
Ayrıca, kullanırsanız @Inject
yapıcı kullanıyorsanız, alan yerleştirmeyi açıkça çağırmak zorunda kalmadan kullanabilirsiniz component.inject(this)
:
public class Something {
@Inject
OtherThing otherThing;
@Inject
public Something() {
}
}
Bu @Inject
yapıcı sınıfları, bunları bir modülde açıkça belirtmek zorunda kalmadan aynı kapsamın bileşenine otomatik olarak eklenir.
Bir @Singleton
kapsamlı @Inject
yapıcı sınıfı görüleceği @Singleton
kapsamlı bileşenler.
@Singleton // scoping
public class Something {
OtherThing otherThing;
@Inject
public Something(OtherThing otherThing) {
this.otherThing = otherThing;
}
}
3.4.) Belirli bir arayüz için belirli bir uygulama tanımladıktan sonra, örneğin:
public interface Something {
void doSomething();
}
@Singleton
public class SomethingImpl {
@Inject
AnotherThing anotherThing;
@Inject
public SomethingImpl() {
}
}
Spesifik uygulamayı arayüze bir @Module
.
@Module
public class SomethingModule {
@Provides
Something something(SomethingImpl something) {
return something;
}
}
Dagger 2.4'den beri bunun için kısa bir el aşağıdaki gibidir:
@Module
public abstract class SomethingModule {
@Binds
abstract Something something(SomethingImpl something);
}
4.) birInjector
uygulama düzeyindeki bileşeninizi işlemek için sınıf (monolitik bileşenin yerini alır ObjectGraph
)
(not: APT kullanarak oluşturucu sınıfı Rebuild Project
oluşturmak için DaggerApplicationComponent
)
public enum Injector {
INSTANCE;
ApplicationComponent applicationComponent;
private Injector(){
}
static void initialize(CustomApplication customApplication) {
ApplicationComponent applicationComponent = DaggerApplicationComponent.builder()
.appContextModule(new AppContextModule(customApplication))
.build();
INSTANCE.applicationComponent = applicationComponent;
}
public static ApplicationComponent get() {
return INSTANCE.applicationComponent;
}
}
5.) sizin oluşturmak CustomApplication
sınıf
public class CustomApplication
extends Application {
@Override
public void onCreate() {
super.onCreate();
Injector.initialize(this);
}
}
6.) ekleyin CustomApplication
adresinden Müşteri AndroidManifest.xml
.
<application
android:name=".CustomApplication"
...
7.) Sınıflarınızı enjekte edinMainActivity
public class MainActivity
extends AppCompatActivity {
@Inject
CustomApplication customApplication;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Injector.get().inject(this);
//customApplication is injected from component
}
}
8.) Keyfini çıkarın!
+1.) Etkinlik düzeyinde kapsamlı bileşenlerScope
oluşturabileceğiniz bileşenlerinizi belirtebilirsiniz . Alt kapsamlar, tüm uygulama boyunca değil, yalnızca belirli bir alt kapsam için ihtiyaç duyduğunuz bağımlılıkları sağlamanıza olanak tanır. Tipik olarak, her Aktivite bu kurulumla kendi modülüne sahip olur. Lütfen kapsamlı bir sağlayıcının mevcut olduğunu unutmayın her bileşen , yani bu etkinliğin örneğini korumak için bileşenin kendisinin konfigürasyon değişikliğinden sağ çıkması gerekir. Örneğin, onRetainCustomNonConfigurationInstance()
bir Harç dürbünüyle hayatta kalabilir .
Alt kapsam oluşturma hakkında daha fazla bilgi için Google kılavuzuna bakın . Ayrıca, sağlama yöntemleri hakkında bu siteye ve ayrıca bileşen bağımlılıkları bölümüne bakın ) ve buraya .
Özel bir kapsam oluşturmak için kapsam niteleyici ek açıklamasını belirtmelisiniz:
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface YourCustomScope {
}
Bir alt kapsam oluşturmak için, bileşeninizdeki kapsamı belirtmeniz ApplicationComponent
ve bağımlılık olarak belirtmeniz gerekir . Açıkçası, alt kapsamı modül sağlayıcı yöntemlerinde de belirtmeniz gerekir.
@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
extends ApplicationComponent {
CustomScopeClass customScopeClass();
void inject(YourScopedClass scopedClass);
}
Ve
@Module
public class CustomScopeModule {
@Provides
@YourCustomScope
public CustomScopeClass customScopeClass() {
return new CustomScopeClassImpl();
}
}
Bağımlılık olarak yalnızca bir kapsamlı bileşenin belirtilebileceğini lütfen unutmayın . Java'da çoklu kalıtımın desteklenmediği gibi düşünün.
+2.) Hakkında@Subcomponent
: esasen, kapsamlı @Subcomponent
bir bileşen bağımlılığının yerini alabilir; ancak açıklama işlemcisi tarafından sağlanan bir oluşturucu kullanmak yerine, bir bileşen fabrikası yöntemi kullanmanız gerekir.
Yani bu:
@Singleton
@Component
public interface ApplicationComponent {
}
@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
extends ApplicationComponent {
CustomScopeClass customScopeClass();
void inject(YourScopedClass scopedClass);
}
Şuna dönüşür:
@Singleton
@Component
public interface ApplicationComponent {
YourCustomScopedComponent newYourCustomScopedComponent(CustomScopeModule customScopeModule);
}
@Subcomponent(modules={CustomScopeModule.class})
@YourCustomScope
public interface YourCustomScopedComponent {
CustomScopeClass customScopeClass();
}
Ve bu:
DaggerYourCustomScopedComponent.builder()
.applicationComponent(Injector.get())
.customScopeModule(new CustomScopeModule())
.build();
Şuna dönüşür:
Injector.INSTANCE.newYourCustomScopedComponent(new CustomScopeModule());
+3.): Lütfen Dagger2 ile ilgili diğer Stack Overflow sorularını da kontrol edin, çok fazla bilgi sağlarlar. Örneğin, mevcut Dagger2 yapım bu cevapta belirtildi .
Teşekkürler
Github , TutsPlus , Joe Steele , Froger MCS ve Google'daki kılavuzlar için teşekkür ederiz .
Ayrıca bu yazıyı yazdıktan sonra bulduğum adım adım geçiş kılavuzu için.
Ve Kirill'in kapsam açıklaması için .
Resmi belgelerde daha fazla bilgi .