1. ホーム
  2. android

[解決済み] AndroidプロジェクトでDAGGER依存性注入をゼロからセットアップする方法とは?

2022-11-14 12:04:56

質問

Daggerはどのように使用するのですか?Androidプロジェクトで動作するようにDaggerを設定する方法を教えてください。

AndroidプロジェクトでDaggerを使用したいのですが、分かりづらいと思います。

EDIT: 2015 04 15からDagger2も出ていますが、さらに分かりにくいです!

[この質問は、Dagger1についてもっと学び、Dagger2についてもっと学んだので、私の答えを追加している"stub"である。この質問は、どちらかというと ガイド 質問というよりは、ガイドです。]

どのように解決するのですか?

のガイド Dagger 2.x (改訂第6版) :

手順は以下の通りです。

1.) 追加 Dagger に、あなたの build.gradle ファイルに追加します。

  • トップレベル 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()
    }
}

  • アプリレベル 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 クラスを作成します。

@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.) 注入できるものを指定するApplication-scopedコンポーネントを作成します(こちらは 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.) あなたが できる を使用して再定義したくないような依存関係。 @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 のコンストラクタ・クラスは、モジュールで明示的に指定しなくても、同じスコープのコンポーネントに自動的に追加されます。

A @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 ビルダークラスを作成します)

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() や Mortar スコープを通して生き残ることができます。

サブスコープの詳細については、以下を参照してください。 によるガイドを参照してください。 . また、次のページもご覧ください。 このサイトでは、提供方法について をご覧ください。 コンポーネント依存性セクション ) と はここで .

カスタムスコープを作成するには、スコープクオリファイアアノテーションを指定する必要があります。

@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();
    }
}

のみであることに注意してください。 1 スコープ付きコンポーネントは依存関係として指定することができます。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.): Dagger2に関する他のStack Overflow質問もチェックしてください、彼らは多くの情報を提供します。たとえば、私の現在のDagger2構造は次のように指定されています。 この回答 .

ありがとうございます

でのガイドをありがとうございました。 Github , ツープラス , ジョー・スティール , フロガー MCS そして グーグル .

また、このために を書いた後に見つけたステップバイステップの移行ガイドです。

そして スコープ説明 をキリルで。

さらに詳しい情報は 公式ドキュメント .