คำแนะนำสำหรับDagger 2.x (ฉบับแก้ไข 6) :
ขั้นตอนมีดังต่อไปนี้:
1. )เพิ่มไฟล์Dagger
ของคุณ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()
}
}
.
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
ชั้นเรียนของคุณที่ให้การอ้างอิง
@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
คลาสที่จัดเตรียมอินเทอร์เฟซเพื่อรับคลาสที่สามารถฉีดได้
public interface AppContextComponent {
CustomApplication application(); //provision method
Context applicationContext(); //provision method
LocationManager locationManager(); //provision method
}
3.1.)นี่คือวิธีที่คุณจะสร้างโมดูลด้วยการใช้งาน:
@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);
}
ข้อควรระวัง:คุณต้องใส่@Scope
คำอธิบายประกอบ (เช่น@Singleton
หรือ@ActivityScope
) ใน@Provides
วิธีการใส่คำอธิบายประกอบของโมดูลเพื่อให้ได้ผู้ให้บริการที่กำหนดขอบเขตไว้ภายในองค์ประกอบที่คุณสร้างขึ้นมิฉะนั้นจะถูกยกเลิกการกำหนดขอบเขตและคุณจะได้รับอินสแตนซ์ใหม่ทุกครั้งที่คุณฉีด
3.2.)สร้างส่วนประกอบขอบเขตแอปพลิเคชันที่ระบุสิ่งที่คุณสามารถฉีดได้ (ซึ่งเหมือนกับinjects={MainActivity.class}
ใน 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.)สำหรับการอ้างอิงที่คุณสามารถสร้างผ่านตัวสร้างด้วยตัวเองและไม่ต้องการกำหนดใหม่โดยใช้ a @Module
(ตัวอย่างเช่นคุณใช้รสชาติของการสร้างแทนเพื่อเปลี่ยนประเภทของการนำไปใช้งาน) คุณสามารถใช้ตัว@Inject
สร้างคำอธิบายประกอบ
public class Something {
OtherThing otherThing;
@Inject
public Something(OtherThing otherThing) {
this.otherThing = otherThing;
}
}
นอกจากนี้หากคุณใช้ตัว@Inject
สร้างคุณสามารถใช้การฉีดฟิลด์ได้โดยไม่ต้องเรียกอย่างชัดเจนcomponent.inject(this)
:
public class Something {
@Inject
OtherThing otherThing;
@Inject
public Something() {
}
}
@Inject
คลาสตัวสร้างเหล่านี้จะถูกเพิ่มลงในส่วนประกอบของขอบเขตเดียวกันโดยอัตโนมัติโดยไม่ต้องระบุอย่างชัดเจนในโมดูล
@Singleton
ขอบเขต@Inject
ระดับคอนสตรัคจะเห็นได้ใน@Singleton
ส่วนประกอบขอบเขต
@Singleton // scoping
public class Something {
OtherThing otherThing;
@Inject
public Something(OtherThing otherThing) {
this.otherThing = otherThing;
}
}
3.4.)หลังจากที่คุณได้กำหนดการใช้งานเฉพาะสำหรับอินเทอร์เฟซที่กำหนดแล้วดังนี้:
public interface Something {
void doSomething();
}
@Singleton
public class SomethingImpl {
@Inject
AnotherThing anotherThing;
@Inject
public SomethingImpl() {
}
}
คุณจะต้อง "ผูก" การใช้งานเฉพาะกับอินเทอร์เฟซด้วยไฟล์@Module
.
@Module
public class SomethingModule {
@Provides
Something something(SomethingImpl something) {
return something;
}
}
ระยะสั้นสำหรับสิ่งนี้เนื่องจาก Dagger 2.4 มีดังต่อไปนี้:
@Module
public abstract class SomethingModule {
@Binds
abstract Something something(SomethingImpl something);
}
4. )สร้างInjector
คลาสเพื่อจัดการองค์ประกอบระดับแอปพลิเคชันของคุณ (แทนที่เสาหินObjectGraph
)
(หมายเหตุ: Rebuild Project
เพื่อสร้างDaggerApplicationComponent
คลาสตัวสร้างโดยใช้ 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. )สร้างCustomApplication
ชั้นเรียนของคุณ
public class CustomApplication
extends Application {
@Override
public void onCreate() {
super.onCreate();
Injector.initialize(this);
}
}
6. )เพิ่มCustomApplication
ในAndroidManifest.xml
ไฟล์.
<application
android:name=".CustomApplication"
...
7. )ใส่คลาสของคุณเข้าMainActivity
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. )สนุก!
+1.)คุณสามารถระบุScope
ส่วนประกอบที่คุณสามารถสร้างองค์ประกอบที่กำหนดขอบเขตระดับกิจกรรมได้ การสมัครสมาชิกอนุญาตให้คุณระบุการอ้างอิงที่คุณต้องการสำหรับขอบเขตย่อยที่กำหนดเท่านั้นแทนที่จะเป็นตลอดทั้งแอปพลิเคชัน โดยปกติแล้วแต่ละกิจกรรมจะมีโมดูลของตัวเองพร้อมกับการตั้งค่านี้ โปรดทราบว่ามีผู้ให้บริการที่กำหนดขอบเขตไว้ตามองค์ประกอบซึ่งหมายความว่าเพื่อรักษาอินสแตนซ์สำหรับกิจกรรมนั้นส่วนประกอบเองจะต้องอยู่รอดจากการเปลี่ยนแปลงการกำหนดค่า ตัวอย่างเช่นมันสามารถอยู่รอดผ่านonRetainCustomNonConfigurationInstance()
หรือขอบเขตปูน
สำหรับข้อมูลเพิ่มเติมเกี่ยว subscoping ตรวจสอบคู่มือที่ Google นอกจากนี้ยังโปรดดูที่เว็บไซต์นี้เกี่ยวกับวิธีการให้และยังพึ่งพาองค์ประกอบส่วน ) และที่นี่
ในการสร้างขอบเขตที่กำหนดเองคุณต้องระบุคำอธิบายประกอบขอบเขตคุณสมบัติ:
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface YourCustomScope {
}
ในการสร้างขอบเขตย่อยคุณต้องระบุขอบเขตบนคอมโพเนนต์ของคุณและระบุApplicationComponent
เป็นการอ้างอิง เห็นได้ชัดว่าคุณต้องระบุขอบเขตย่อยในวิธีการให้บริการโมดูลด้วย
@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
extends ApplicationComponent {
CustomScopeClass customScopeClass();
void inject(YourScopedClass scopedClass);
}
และ
@Module
public class CustomScopeModule {
@Provides
@YourCustomScope
public CustomScopeClass customScopeClass() {
return new CustomScopeClassImpl();
}
}
โปรดทราบว่าสามารถระบุคอมโพเนนต์ที่กำหนดขอบเขตได้เพียงรายการเดียวเพื่ออ้างอิง ลองคิดดูว่า Java ไม่รองรับการสืบทอดหลายรายการ
+2.)เกี่ยวกับ@Subcomponent
: โดยพื้นฐานแล้วขอบเขต@Subcomponent
สามารถแทนที่การพึ่งพาส่วนประกอบได้ แต่แทนที่จะใช้ตัวสร้างที่จัดเตรียมโดยโปรเซสเซอร์คำอธิบายประกอบคุณจะต้องใช้วิธีการโรงงานส่วนประกอบ
ดังนั้นสิ่งนี้:
@Singleton
@Component
public interface ApplicationComponent {
}
@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
extends ApplicationComponent {
CustomScopeClass customScopeClass();
void inject(YourScopedClass scopedClass);
}
กลายเป็นสิ่งนี้:
@Singleton
@Component
public interface ApplicationComponent {
YourCustomScopedComponent newYourCustomScopedComponent(CustomScopeModule customScopeModule);
}
@Subcomponent(modules={CustomScopeModule.class})
@YourCustomScope
public interface YourCustomScopedComponent {
CustomScopeClass customScopeClass();
}
และนี่:
DaggerYourCustomScopedComponent.builder()
.applicationComponent(Injector.get())
.customScopeModule(new CustomScopeModule())
.build();
กลายเป็นสิ่งนี้:
Injector.INSTANCE.newYourCustomScopedComponent(new CustomScopeModule());
+3.):โปรดตรวจสอบคำถาม Stack Overflow อื่น ๆ เกี่ยวกับ Dagger2 ด้วยเช่นกันพวกเขาให้ข้อมูลมากมาย ตัวอย่างเช่นโครงสร้าง Dagger2 ปัจจุบันของฉันถูกระบุไว้ในคำตอบนี้
ขอบคุณ
ขอบคุณสำหรับคำแนะนำที่Github , TutsPlus , โจสตีล , Froger MCSและGoogle
นอกจากนี้สำหรับคำแนะนำการย้ายทีละขั้นตอนนี้ฉันพบหลังจากเขียนโพสต์นี้
และสำหรับคำอธิบายขอบเขตโดย Kirill
ข้อมูลเพิ่มเติมในเอกสารอย่างเป็นทางการ