中 2016年2月12日。 この記事の目的は、 Dagger 2の基本的なメカニズムを理解することです。
ダガーの仕組みを説明するチュートリアルのほとんどは複雑すぎることがわかりました。 Google / Squareガイドでさえ、 依存性注入がどのように機能するかについて明確な考えがない限り、理解するのは難しすぎます。
これを理解するために、 Daggerの動作を示すいくつかのクラスを持つ非常に単純なJavaプロジェクトを作成しました。
この記事では、 Daggerの主要コンポーネントについて説明します。 この記事は、このライブラリを使用しないで計画している人を対象としています。
プロジェクト構造
apply plugin: 'java' repositories { jcenter() } dependencies { testCompile 'junit:junit:4.12' compile 'com.google.dagger:dagger:2.0' compile 'com.google.dagger:dagger-compiler:2.0' }
これはbuild.gradleファイルのコードです。 単体テストの作成には、標準のJavaプラグインとJUnitが使用されます。 dagger-compilerライブラリーを追加することを忘れないでください(これは私の最初の間違いでした)。
短剣コンパイラの依存関係に関する子馬からのメモ:
Dagger‡およびその他のAPTベースの製品の場合、gradle-apt-pluginを使用することをお勧めします。 これにより、コードのコンパイル用と生成用の2つの異なるクラスパスが混同されないため、プロジェクトのコンパイルがより透明で安全になります。
コードを見せて
この例には2つのクラスがあります。
- GameData:このクラスは、 GameSessionクラスに必要なデータを提供します。 私たちの場合、それは単なる文字列です。
- GameSession:このクラスにはGameDataが必要です 。 GameDataパラメーターを渡すか、 GameSession内にインスタンスを作成する代わりに、 Daggerを使用して依存関係を実装します。
依存性注入がなければ 、次のようなことが起こります。GameDataクラスはGameSession内に作成されます。 一部の開発者は、これが悪い習慣であることに同意するでしょう。 たとえば、テストにGameDataの別のインスタンスが必要な場合、作成することはできません。
public class GameData { public final String hello = "Hello Dagger"; }
public class GameSession { public GameData data = new GameData(); }
DaggerはGameDataクラスのインスタンスをGameSessionクラス変数に導入してくれます 。
@Inject
アノテーションを使用してこれを示すことだけが必要です。
public class GameData { public final String hello = "Hello Dagger"; }
import javax.inject.Inject; public class GameSession { @Inject public GameData data; }
次に、依存性注入の実装方法を決定するクラスを作成する必要があります。これらはComponentとModuleです。
- モジュールはすべての注入プロバイダーを定義します。 つまり、依存クラスでの実装のために特定のインスタンスを返すメソッドを定義します。 この場合、 GameDataを返送するプロバイダーを決定する必要があります。
- コンポーネントは、 Daggerがコードを生成して依存関係を注入するために使用するインターフェイスです。
import dagger.Component; @Component(modules = GameModule.class) public interface GameComponent { void inject(GameSession obj); }
import dagger.Module; import dagger.Provides; @Module public class GameModule { @Provides GameData providesGameData() { return new GameData(); } }
- GameModuleには、これがGameDataのインスタンスを返す関数の1つであることをDaggerに伝える
@Provides
注釈付きの関数が含まれています。 - また、 GameModuleクラスに@Moduleアノテーションを付ける必要があります。
- GameComponentインターフェイスはインジェクション関数を定義します。 この関数はGameSessionクラスで使用され、 GameDataクラスのインスタンスをそれに挿入します。これはGameModule.providesGameData()関数を返します。
この瞬間、すべての魔法は包まれます。 Daggerは、 GameSessionクラスがGameDataクラスを必要とし、 GameModuleクラスがGameDataインスタンスの受信方法を決定することを理解します。 GameSessionクラスから呼び出されるインジェクションを開始するには、 GameComponentインターフェイスを使用する必要があります。
コンポーネントを使用する
次の単体テストは、 コンポーネントタイプの生成されたクラスを使用して、インスタンス化されたGameSessionクラスにGameDataクラスを埋め込む方法を示しています。
import org.junit.Test; import static org.junit.Assert.*; public class GameSessionTest { @Test public void testGameSession() { GameSession session = new GameSession(); DaggerGameComponent.create().inject(session); assertEquals("Hello Dagger", session.data.hello); } }
- DaggerGameComponentクラスは 、 create()関数を含むDaggerによって生成されます。
- このクラスは、 Inject ()メソッドを呼び出してGameSessionのインスタンスを渡すことができるGameComponentインターフェイスを実装します。
- inject()メソッドは 、 GameSessionのすべての依存関係を注入します。
- 最後に、 GameSessionクラスのデータフィールドの値が設定されていることがわかります。
この例は単純で、 Daggerの多くの機能を逃しています。 先ほど言ったように、この例は基本を理解するのに役立ちました。あなたにも役立つことを願っています。
Dagger 2の動作方法の基本的な理解が得られたので、元のドキュメントに戻ってCoffeeMakerで例を解析することをお勧めします。