2017-04-12 6 views
12

新しい(2.10の)dagger.androidクラスを使用して、私は他のモジュールに依存するサブコンポーネントを使用して物事を注入しようとしています。 https://google.github.io/dagger/android.htmlのドキュメントではこれについて説明していますが、実際にこれらのセッターを書き込んだり呼び出す方法は不明です。上記のリンクから引用Dagger 2.10 Androidサブコンポーネントとビルダー

AndroidInjection.inject() gets a DispatchingAndroidInjector from the Application and passes your activity to inject(Activity). The DispatchingAndroidInjector looks up the AndroidInjector.Factory for your activity’s class (which is YourActivitySubcomponent.Builder), creates the AndroidInjector (which is YourActivitySubcomponent), and passes your activity to inject(YourActivity).

Builderのセッターを呼び出すことができるようにするために、私はどこかに取得し、Builderは、必要なすべてを持っていることを確認する必要があると私には思えますデータ?私が見ている問題は、実行時に、サブコンポーネントの生成されたビルダーがAndroidInjectorによって呼び出されたときにIllegalStateException: MODULE must be setを取得することです。

問題のサブコンポーネントは、実際にはアクティビティではなくフラグメントですが、重要であるかどうかはわかりません。これを行う方法についての任意のアイデア?

+1

[this](https://android.jlelse.eu/android-and-dagger-2-10-androidinjector-5e9c523679a3)をご覧ください。ほとんどの場合、あなたの質問が解決されます。 – azizbekian

+1

簡単なコードを投稿できますか?どのモジュールを設定できませんか? –

答えて

25

要するに、必要な他のモジュールを提供するために、Builderではoverride the call to seedInstance(インターフェイスではなく抽象クラス)となっています。

edit:確認する前に、実際にそのモジュールを渡す必要があることを確認してください。 Damon added in a separate answerとして、あなたのAndroidクラス用に特定のモジュールを作成している場合は、そのクラスの自動注入を利用して、その時点でグラフから構成またはインスタンスを取り出すことができます。モジュールからコンストラクタパラメータを削除するほうが簡単な場合は、不必要なインスタンスや仮想メソッド呼び出しを避けるため、パフォーマンスが向上する可能性があります。


まず、30秒dagger.android:ではなく、各アクティビティまたはその断片を有するが、その親、活性(またはその断片)について知っているが、HasActivityInjectorのアプリケーション(または親フラグメントをチェックする、AndroidInjection.inject(this)を呼び出し活動、及びHasFragmentInjectorの申請)。考えられるのは、マルチバインディングにバインディングを提供するということです。寄付されたバインディングはです。常に作成するサブコンポーネントビルダーはビルドオブジェクト固有のサブコンポーネントです。

AndroidInjection.inject(this)AndroidInjector.Factory.create(T instance)からお分かりのように、アクティビティ固有またはフラグメント固有の詳細をBuilderに渡す機会は多くありません。代わりに、サブコンポーネントビルダーがseedInstanceの実装よりも優先されるという考えがあります。

Provides instance to be used in the binding graph of the built AndroidInjector . By default, this is used as a BindsInstance method, but it may be overridden to provide any modules which need a reference to the activity.

This should be the same instance that will be passed to inject(Object) .

このような何かになりたい::seedInstanceためのドキュメントのように

@Subcomponent(modules = {OneModule.class, TwoModule.class}) 
public interface YourActivitySubcomponent extends AndroidInjector<YourActivity> { 

    // inject(YourActivity) is inherited from AndroidInjector<YourActivity> 

    @Builder 
    public abstract class Builder extends AndroidInjector.Builder<YourActivity> { 
    // Here are your required module builders: 
    abstract Builder oneModule(OneModule module); 
    abstract Builder twoModule(TwoModule module); 

    // By overriding seedInstance, you don't let Dagger provide its 
    // normal @BindsInstance implementation, but you can supply the 
    // instance to modules or call your own BindsInstance: 
    @Override public void seedInstance(YourActivity activity) { 
     oneModule(new OneModule(activity)); 
     twoModule(new TwoModule(activity.getTwoModuleParameter())); 
    } 
    } 
} 

をここでの仮定は、あなたがモジュールに対してactivityインスタンスを待つ必要があるということです。ない場合は、サブコンポーネントバインドするとき、あなたはまた、これらの呼び出しのオプションがあります:

@Provides @IntoMap @ActivityKey(YourActivity.class) 
AndroidInjector.Factory bindInjector(YourActivitySubcomponent.Builder builder) { 
    return builder 
     .oneModule(new OneModule(...)) 
     .twoModule(new TwoModule(...)); 
} 

を...しかし、あなたはそれを行うことができれば、あなたはもっと、簡単にそれらのモジュールをオーバーライドすることによって、それらのバインディングの世話をすることができモジュールのコンストラクタパラメータを提供することができるゼロ引数コンストラクタを実装し、Daggerがパブリックゼロ引数コンストラクタを持つ任意のモジュールに対してそれらを作成させるようにします。

+0

パーフェクト、ありがとう! –

+2

これは完全に機能しました!しかし、ドキュメントのどこにも言及されていませんでしたが、これは、ダガー2を使って新しいユーザーが理解するのを難しくしています。 – ArunL

+0

実装で「エラー:(154、5)エラー:メソッドがスーパータイプのメソッドをオーバーライドまたは実装しない」というエラーが返される理由がわかりません。 –

2

動作しますが、不要です。 seedInstanceメソッドはアクティビティインスタンスをグラフに提供するので、MyActivityModuleを状態なしにして、@ProvidesメソッドでMyActivityを要求することができます。

class MyActivityModule { 
    @Provides 
    static SomethingDerivedFromMyActivity providesMethod(MyActivity myActivity) { 
    return myActivity.somethingDerived(); 
    } 
} 

これを実行すると、モジュールインスタンスが保存され、生成されたファクトリがより希薄になります。

https://github.com/google/dagger/issues/615

+0

+1:あなたとあなたのチームのメンバーであるRonは、あなたの設定があなたのアクティビティへの参照を含むようにモジュールを編集するのに十分なリファクタリングが可能であると仮定して、もちろんそうです。あなたのモジュールが第三者から提供されている場合や、MyActivity以外のアクティビティで動作するように設計されている場合は、より複雑な設定(ドキュメント自体でも示唆されています)を行う必要があります。ビルダーの必要性について言及したので、Askerがコンストラクタを持つステートフルなモジュールを必要としていると仮定して、この質問に答えました。しかし、あなたがしなければ、より簡単に表現することができます。 –

+0

同意しますが、私の問題は、あなたのソリューションを使用するとき、コンパイラが "Error:(154、5)error:メソッドがスーパータイプのメソッドをオーバーライドまたは実装しない"という大きな騒ぎに抗議するということです。私は完全に手順に従っており、生成されたコードを確認した後、 'oneModule()'抽象メソッドの実装でエラーが発生しています。なぜそれが起こるかわからないし、私は短剣2.10を使用しています。とにかく、もう少しテストをしましょう。私のコードで間違ったところが見つかるかもしれません。 –

+0

私を見せてもらえますか? 'oneModule'はパブリックでも抽象でもなく、クラスもそうでなかったか、そうでないようです。 –

関連する問題