Panduan untuk Dagger 2.x (Edisi Revisi 6) :
Langkah-langkahnya adalah sebagai berikut:
1.) tambahkan Dagger
ke build.gradle
file Anda :
- tingkat atas build.gradle :
.
// 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()
}
}
- tingkat aplikasi 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.) Buat AppContextModule
kelas Anda yang menyediakan dependensi.
@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.) membuat AppContextComponent
kelas yang menyediakan antarmuka untuk mendapatkan kelas yang dapat diinjeksi.
public interface AppContextComponent {
CustomApplication application(); //provision method
Context applicationContext(); //provision method
LocationManager locationManager(); //provision method
}
3.1.) Beginilah cara Anda membuat modul dengan implementasi:
@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);
}
Hati-hati:: Anda perlu memberikan @Scope
anotasi (suka @Singleton
atau @ActivityScope
) pada @Provides
metode anotasi modul untuk mendapatkan penyedia yang tercakup dalam komponen yang Anda buat, jika tidak maka akan tidak tercakup, dan Anda akan mendapatkan instance baru setiap kali Anda memasukkan.
3.2.) Buat komponen Cakupan aplikasi yang menentukan apa yang dapat Anda masukkan (ini sama dengan yang ada injects={MainActivity.class}
di Dagger 1.x):
@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.) Untuk dependensi yang dapat Anda buat sendiri melalui konstruktor dan tidak ingin didefinisikan ulang menggunakan a @Module
(misalnya, Anda menggunakan ragam build sebagai gantinya untuk mengubah jenis implementasi), Anda dapat menggunakan @Inject
konstruktor beranotasi.
public class Something {
OtherThing otherThing;
@Inject
public Something(OtherThing otherThing) {
this.otherThing = otherThing;
}
}
Selain itu, jika Anda menggunakan @Inject
konstruktor, Anda dapat menggunakan injeksi bidang tanpa harus memanggil secara eksplisit component.inject(this)
:
public class Something {
@Inject
OtherThing otherThing;
@Inject
public Something() {
}
}
Ini @Inject
kelas konstruktor secara otomatis ditambahkan ke komponen lingkup yang sama tanpa harus secara eksplisit menentukan mereka dalam modul.
Sebuah @Singleton
scoped @Inject
kelas konstruktor akan terlihat dalam @Singleton
komponen scoped.
@Singleton // scoping
public class Something {
OtherThing otherThing;
@Inject
public Something(OtherThing otherThing) {
this.otherThing = otherThing;
}
}
3.4.) Setelah Anda menentukan implementasi khusus untuk antarmuka tertentu, seperti:
public interface Something {
void doSomething();
}
@Singleton
public class SomethingImpl {
@Inject
AnotherThing anotherThing;
@Inject
public SomethingImpl() {
}
}
Anda harus "mengikat" penerapan khusus ke antarmuka dengan file @Module
.
@Module
public class SomethingModule {
@Provides
Something something(SomethingImpl something) {
return something;
}
}
Singkatnya untuk ini karena Dagger 2.4 adalah sebagai berikut:
@Module
public abstract class SomethingModule {
@Binds
abstract Something something(SomethingImpl something);
}
4.) buat Injector
kelas untuk menangani komponen tingkat aplikasi Anda (menggantikan monolitik ObjectGraph
)
(catatan: Rebuild Project
untuk membuat DaggerApplicationComponent
kelas pembangun menggunakan APT)
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.) buat CustomApplication
kelas Anda
public class CustomApplication
extends Application {
@Override
public void onCreate() {
super.onCreate();
Injector.initialize(this);
}
}
6.) tambahkan CustomApplication
ke AndroidManifest.xml
.
<application
android:name=".CustomApplication"
...
7.) Masukkan kelas AndaMainActivity
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.) Selamat menikmati!
+1.) Anda dapat menentukan Scope
untuk komponen Anda yang dengannya Anda dapat membuat komponen cakupan tingkat Aktivitas . Langganan memungkinkan Anda menyediakan dependensi yang hanya Anda perlukan untuk subskop tertentu, bukan di seluruh aplikasi. Biasanya, setiap Aktivitas mendapatkan modulnya sendiri dengan penyiapan ini. Harap diperhatikan bahwa penyedia terbatas ada per komponen , artinya untuk mempertahankan instance untuk aktivitas itu, komponen itu sendiri harus bertahan dari perubahan konfigurasi. Misalnya, itu bisa bertahan melalui onRetainCustomNonConfigurationInstance()
, atau lingkup Mortar.
Untuk info lebih lanjut tentang berlangganan, lihat panduan oleh Google . Juga silakan lihat situs ini tentang metode penyediaan dan juga bagian ketergantungan komponen ) dan di sini .
Untuk membuat cakupan khusus, Anda harus menentukan anotasi pengualifikasi cakupan:
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface YourCustomScope {
}
Untuk membuat subskop, Anda perlu menentukan cakupan pada komponen Anda, dan menentukan ApplicationComponent
sebagai ketergantungannya. Jelas Anda juga perlu menentukan subskop pada metode penyedia modul.
@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
extends ApplicationComponent {
CustomScopeClass customScopeClass();
void inject(YourScopedClass scopedClass);
}
Dan
@Module
public class CustomScopeModule {
@Provides
@YourCustomScope
public CustomScopeClass customScopeClass() {
return new CustomScopeClassImpl();
}
}
Harap diperhatikan bahwa hanya satu komponen cakupan yang dapat ditentukan sebagai dependensi. Anggap saja persis seperti bagaimana multiple inheritance tidak didukung di Java.
+2.) Tentang @Subcomponent
: pada dasarnya, cakupan @Subcomponent
dapat menggantikan ketergantungan komponen; tetapi alih-alih menggunakan builder yang disediakan oleh pemroses anotasi, Anda harus menggunakan metode pabrik komponen.
Jadi ini:
@Singleton
@Component
public interface ApplicationComponent {
}
@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
extends ApplicationComponent {
CustomScopeClass customScopeClass();
void inject(YourScopedClass scopedClass);
}
Menjadi ini:
@Singleton
@Component
public interface ApplicationComponent {
YourCustomScopedComponent newYourCustomScopedComponent(CustomScopeModule customScopeModule);
}
@Subcomponent(modules={CustomScopeModule.class})
@YourCustomScope
public interface YourCustomScopedComponent {
CustomScopeClass customScopeClass();
}
Dan ini:
DaggerYourCustomScopedComponent.builder()
.applicationComponent(Injector.get())
.customScopeModule(new CustomScopeModule())
.build();
Menjadi ini:
Injector.INSTANCE.newYourCustomScopedComponent(new CustomScopeModule());
+3.): Silakan periksa pertanyaan Stack Overflow lainnya tentang Dagger2 juga, mereka memberikan banyak info. Misalnya, struktur Dagger2 saya saat ini ditentukan dalam jawaban ini .
Terima kasih
Terima kasih untuk panduan di Github , TutsPlus , Joe Steele , Froger MCS dan Google .
Juga untuk panduan migrasi langkah demi langkah ini yang saya temukan setelah menulis posting ini.
Dan untuk penjelasan ruang lingkup oleh Kirill.
Lebih banyak informasi di dokumentasi resmi .