2016-10-20 7 views
0
Android Studio 2.2.2 

私はMVPのモデルであるNewsListModelImpクラスを持っています。dagger2を使用して、アクティビティやフラグメントを持たないjavaクラスに挿入する方法

モデルに私のレトロフィットサービスを注入したいと思います。しかし、NewsListModelImpにはコンテキストやアクティビティへの参照が含まれていないため、getApplication()と呼ぶことはできません。あなたが活動や断片化している場合、あなたがすることは何でしょうか。私はNewsListModeImpのコンストラクタでコンテキストやアクティビティを渡すことは望ましくありません。プレゼンターから来なければならないので、そこにはアンドロイドのものは避けたいと思っています。

public class NewsListModelImp implements NewsListModelContract { 
    @Inject 
    NYTimesSearchService mNYTimesSearchService; 

    public NewsListModelImp() { 
     ((NYTimesSearchApplication)getApplication()).getAppComponent().inject(this); 
    } 
} 

マイApplicationクラス

public class NYTimesSearchApplication extends Application { 
    private AppComponent mAppComponent; 

    public void onCreate() { 
     super.onCreate(); 

     /* Setup dependency injection */ 
     createAppComponent(); 
    } 

    private void createAppComponent() { 
     mAppComponent = DaggerAppComponent 
       .builder() 
       .retrofitModule(new RetrofitModule()) 
       .build(); 
    } 

    public AppComponent getAppComponent() { 
     return mAppComponent; 
    } 
} 

マイモジュール

@Module 
public class RetrofitModule { 
    private Retrofit retrofit() { 
     return new Retrofit 
       .Builder() 
       .baseUrl(Constants.BASE_URL) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 
    } 

    @Provides 
    @Singleton 
    public NYTimesSearchService providesNYTimesSearch() { 
     return retrofit().create(NYTimesSearchService.class); 
    } 
} 

マイAppcomponentに任意の提案のための

@Singleton 
@Component(modules = {RetrofitModule.class}) 
public interface AppComponent { 
    void inject(NewsListModelImp target); 
} 

多くのおかげで、

を提供10

答えて

3

Dagger-2が好評です。したがって、内部にActivity(またはFragment)オブジェクトが注入され、そのコンストラクタに@Inject注釈が正しく注釈されている場合、コンストラクタのパラメータも注入されます。

あなたが注入したいアプリケーション内とします

@Inject NyTimesPresenter presenter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    ((NYTimesSearchApplication) getApplication()).getAppComponent().inject(this); 
} 

NyTimesPresenterのコンストラクタが@Injectで注釈されている必要があります

public class NyTimesPresenter { 

    NewsListModelImp newsListModel; 

    @Inject 
    public NyTimesPresenter(NewsListModelImp newsListModel) { 
     this.newsListModel = newsListModel; 
    } 
} 

NewsListModelImpコンストラクタも@Injectで注釈されている必要があります

public class NewsListModelImp implements NewsListModelContract { 

    NYTimesSearchService mNYTimesSearchService; 

    @Inject 
    public NewsListModelImp(NYTimesSearchService nYTimesSearchService) { 
     this.mNYTimesSearchService = nYTimesSearchService; 
    } 
} 

それからすべてが適切に注入されます。

なぜパラメータをコンストラクタのパラメータとしてクラスに渡す必要がありますか?このようなデザインパターンはSOLID principlesに準拠しています。オブジェクト依存関係は(テストでの依存関係、すなわち交換することができるMockのにより)オブジェクトに注入し、その中に作成されていないと、そのようなコードは簡単にテスト可能であるれる

EXTRA INFO:

オブジェクトを注入することが可能です特定のインターフェイスを実装します。このような技術は、hereと記載されている。あなたの場合、NyTimesPresenterNewsListModelImpの代わりにNewsListModelContractを持つことができます。これはあなたのAppComponentに別のモジュールを追加してください。

@Singleton 
@Component(
     modules = { 
       RetrofitModule.class, 
       AppModule.class 
     }) 
public interface AppComponent { 

AppComponent方法のようになりますインターフェイスを実装する具体的なクラスを提供すること:

@Singleton 
@Module 
public abstract class AppModule { 

    @Binds 
    public abstract NewsListModelContract provideNewsListModelContract(NewsListModelImp newsListModelImp); 
} 
NyTimesPresenterの実装が変更する必要があり

は(単にインターフェースを持つ具象クラスを交換しますそれは実装しています):

public class NyTimesPresenter { 

    NewsListModelContract newsListModel; 

    @Inject 
    public NyTimesPresenter(NewsListModelContract newsListModel) { 
     this.newsListModel = newsListModel; 
    } 
} 
関連する問題