[解決済み] AndroidプロジェクトでDAGGER依存性注入をゼロからセットアップする方法とは?
質問
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 そして グーグル .
また、このために を書いた後に見つけたステップバイステップの移行ガイドです。
そして スコープ説明 をキリルで。
さらに詳しい情報は 公式ドキュメント .
関連
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] AndroidのListViewで画像を遅延ロードする方法
-
[解決済み] アプリケーションを終了することは嫌われますか?
-
[解決済み] Inversion of ControlとDependency Injectionの比較
-
[解決済み] なぜ依存性注入を使用するのですか?
-
[解決済み] Androidで、dpの余白をプログラムで設定する方法を教えてください。
-
[解決済み] ArrayAdapter<myClass> の使用方法
-
[解決済み] キャンバスに複数行のテキストを描画する
-
[解決済み] PendingIntentの "requestCode "は何に使うのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 設定ページに移動せずに位置情報サービスをオンにする
-
[解決済み] ViewPagerのアイテムを強制的に再インスタンス化する方法 [重複].
-
[解決済み] wrap_contentでRelativeLayoutがフルスクリーンになってしまう
-
[解決済み] EclipseのAndroidプロジェクトにライブラリ/JARを追加する
-
[解決済み] AsyncTaskを複数回実行する
-
[解決済み] react nativeアプリのバージョン番号を更新する方法
-
[解決済み] PendingIntentの "requestCode "は何に使うのですか?
-
[解決済み] Androidでツールバーの戻るボタンの色を変えるには?
-
[解決済み] Recyclerviewと異なるタイプの行のインフレーションの処理
-
[解決済み] <string> XMLで改行やタブを作るには(eclipse/android)?