9

私の質問はthisに似ています。ダガー2(アクティビティスコープ内)を使用したカスタムビューの依存関係注入

だから例えば、私はLiveData実装を持っている:

私は、カスタムビューに注入したい
public class CustomLiveData extends LiveData<SomeEvent> { 

    @Inject 
    public CustomLiveData(@ActivityContext Context context) { 
     //.... 
    } 

} 

public class CustomView extends View { 
    @Inject 
    SomeApplicationProvider anyProvider; 

    @Inject 
    CustomLiveData dataProvider; 
    // Getting @com.di.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method. 
    // @com.di.qualifiers.ActivityContext android.content.Context is injected at com.repositories.CustomLiveData.<init>(context) 
    // com.repositories.CustomLiveData is injected at com.ui.CustomView.dataProvider com.ui.CustomView is injected at 
    // com.di.ApplicationComponent.inject(view) 

    public CustomView(Context context) { this(context, null); } 
    public CustomView(Context AttributeSet attrs) { 
     super(context, attrs); 

     // Works ok for application provider 
     Application.getComponent(context).inject(this); 
    } 
} 

そしてここでは、DIクラスの残りの部分であります

@ApplicationScope 
@Component(
     modules = {AndroidInjectionModule.class, 
       ActivityBuilder.class 
     }) 

public interface ApplicationComponent extends AndroidInjector<MyApp> { 

    void inject(MyApp application); 

    void inject(CustomView view); 

    @Component.Builder 
    abstract class Builder extends AndroidInjector.Builder<MyApp> { 

     public abstract ApplicationComponent build(); 
    } 
} 

@ActivityScope 
@Module (subcomponents = MainActivitySubcomponent.class) 
public abstract class ActivityBuilder { 

    @Binds 
    @IntoMap 
    @ActivityKey(MainActivity.class) 
    abstract AndroidInjector.Factory<? extends Activity> 
    bindActivityInjectorFactory(MainActivitySubcomponent.Builder builder); 

    //... 

} 


@Subcomponent(modules = {MainActivityModule.class}) 
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> { 

    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<MainActivity> { 

    } 
} 

@ActivityScope 
@Module 
public class MainActivityModule { 

    @Provides 
    @ActivityContext 
    public Context provideActivityContext(MainActivity activity) { 
     return activity; 
    } 

    // Seems to be wrong or not enough!? 
    @Provides 
    public CustomLiveData provideCustomLiveData(@ActivityContext Context context) { 
     return new CustomLiveData(context); 
    } 
} 


@Qualifier 
public @interface ActivityContext{ 
} 

の場合、コンパイラの苦情はありません。がビューにではなくMainActivityに注入されます。 ありがとう!

+0

'CustomLiveData'を' Custom'ビューに注入するとコンパイルエラーが発生しましたか?あなたの質問と一緒に投稿してください。 –

+0

メッセージがCustomView部分に含まれていました。 "// @ com.di.qualifiers.ActivityContext android.content.Contextを取得できません"を参照してください。 – sinek

+0

'@ ActivityContext'を投稿できますか? –

答えて

13

TL; DRは、カスタムViewViewのオブジェクト

サブクラス内のモデル層の依存関係を注入しないでくださいはダガー2注入のための良好な標的ではありません。 Viewオブジェクトは描画されることを意図されているため、他には必要ではないため、「ビュー」という名前が付けられています。 Viewのコンストラクタはこれを明確にする必要があります。それらはXMLで指定された属性からViewオブジェクトを膨張させるように設計されています。つまり、Viewオブジェクトをlayout.xmlファイルで指定し、ライフサイクルの適切な時点で膨張させ、次にfindViewById(int id),Butterknifeまたはデータバインディングを使用して取得できるようにする必要があります。このようにして、最良のカスタムオブジェクトViewは依存関係を持ちません。

モデルレイヤーのViewといくつかのデータをリンクする場合、標準パターンはRecyclerViewListViewのようなアダプタを記述することです。これが不可能な場合は、コンストラクタ内のモデルレイヤからの依存関係を渡すか、Viewのライフサイクルメソッドの1つからの注入を要求するよりも、セッター(たとえば、setData())を使用することをお勧めします。

AndroidInjectorクラスを使用してアクティビティまたはフラグメント内にLiveDataオブジェクトを挿入すると、何もすることなく正しいContextが提供されます。これはあなたのコメントを説明しています。「CustomLiveDataがMainActivityにビューの代わりに注入されていると、コンパイラの不満はありません。

LiveDataオブジェクトをアクティビティに挿入したら、上記の方法の1つ(アダプタまたは設定者)を使用して、データをカスタムViewに関連付けます。

:モデル層からの要素がダガー2を使用して注入し、次いでListViewViewオブジェクトの注入が議論されているダガー2号へfindViewByIdsetAdapter()

リンクを使用して関連付けられているGoogleのAndroidアーキテクチャ例hereを参照https://github.com/google/dagger/issues/720

1

あなたのダガー階層は次のようになります。 appcomponent - >activitycomponent

あなたが直接appcomponentに依存している、ビュー内の活動contextを注入してみてください。

appcomponentにアクティビティコンテキストを提供する方法がないため、これは不可能です。代わりに、内部ビュー(たとえばgetContextを使用して)を取得し、そこからactivitycomponentを抽出してからCustomLiveDataを注入する必要があります。

関連する問題