I'm trying to implement Retrofit within my project using dagger 2 and it gives me the below error:
Error:(22, 10) error: com.toranj.tyke.restApi.LotteryApiInterface cannot be provided without an #Provides- or #Produces-annotated method.
com.toranj.tyke.restApi.LotteryApiInterface is injected at
com.toranj.tyke.ui.MainActivity.LotteryApiInterface
com.toranj.tyke.ui.MainActivity is injected at
com.toranj.tyke.dagger.components.NetworkComponent.inject(activity)
so here is my LotteryApiInterface:
public interface LotteryApiInterface {
#GET("/lottery/search")
Call<List<Lottery>> getByCriteria(#Query("q") String query);
#GET("lottery/details")
Call<Lottery> getById(#Query("Id") String id);
}
and here is the LotteryComponent:
#PerActivity
#Component(dependencies = NetworkComponent.class, modules = LotteryModule.class)
public interface LotteryComponent {
void inject(MainActivity activity);
}
and there goes my LotteryModule:
#Module
public class LotteryModule {
#Provides
#PerActivity
public LotteryApiInterface providesLotteryApiInterface(Retrofit retrofit) {
return retrofit.create(LotteryApiInterface.class);
}
}
when I Clean > Rebuild the project it gives me the error even though my LotteryModule has the #Provides annotation for the object.
Probably I'm missing something in here. Any help is appreciated.
EDIT: Retrofit is created in my Application class as below:
public class TykeApp extends Application {
private NetworkComponent networkComponent;
#Override
public void onCreate() {
super.onCreate();
networkComponent = DaggerNetworkComponent.builder()
.appModule(new AppModule(this))
.networkModule(new NetworkModule("http://192.168.0.3:8080"))
.build();
}
public NetworkComponent getNetworkComponent() {
return networkComponent;
}
}
NetworkComponent:
#Singleton
#Component(modules = { AppModule.class, NetworkModule.class })
public interface NetworkComponent {
void inject(MainActivity activity);
Retrofit retrofit();
OkHttpClient okHttpClient();
SharedPreferences sharedPreferences();
}
NetworkModule:
#Module
public class NetworkModule {
String baseUrl;
public NetworkModule(String baseUrl) {
this.baseUrl = baseUrl;
}
#Provides
SharedPreferences provideSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
#Provides
OkHttpClient provideOkhttpClient() {
OkHttpClient.Builder client = new OkHttpClient.Builder();
return client.build();
}
#Provides
Retrofit provideRetrofit(OkHttpClient httpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
.client(httpClient)
.build();
}
}
and this is the MainActivity:
public class MainActivity extends BaseActivity {
#Inject
Retrofit retrofit;
#Inject
LotteryApiInterface LotteryApiInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((TykeApp)getApplication()).getNetworkComponent().inject(this);
LotteryComponent lotteryComponent = DaggerLotteryComponent.builder()
.lotteryModule(new LotteryModule())
.build();
lotteryComponent.inject(this);
}
}
When I use
#Inejct
LotteryApiInterface LotteryApiInterface;
it throws the given error message.
When you use field injection in Dagger2, then your component that you use component.inject(this); with needs to be able to provide every dependency that you marked with #Inject.
This means that in your case, you shouldn't have
((TykeApp)getApplication()).getNetworkComponent().inject(this);
And instead you're supposed to have
LotteryComponent lotteryComponent = DaggerLotteryComponent.builder()
.networkComponent(((TykeApp)getApplication()).getNetworkComponent())
.lotteryModule(new LotteryModule())
.build();
lotteryComponent.inject(this);
But it's worth noting that your network module should be
#Module
public class NetworkModule {
String baseUrl;
public NetworkModule(String baseUrl) {
this.baseUrl = baseUrl;
}
#Provides
SharedPreferences provideSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
#Provides
#Singleton
OkHttpClient provideOkhttpClient() {
OkHttpClient.Builder client = new OkHttpClient.Builder();
return client.build();
}
#Provides
#Singleton
Retrofit provideRetrofit(OkHttpClient httpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
.client(httpClient)
.build();
}
}
And your NetworkComponent should be
#Singleton
#Component(modules = { AppModule.class, NetworkModule.class })
public interface NetworkComponent {
Retrofit retrofit();
OkHttpClient okHttpClient();
SharedPreferences sharedPreferences();
}
Related
I have an application which fetches the type ahead search values.I m using dagger for dependency injection.However dagger is injecting the values for activity class but not injecting for other classes
Modules
#Module
public class NetModule {
String baseURL;
public NetModule(String baseURL){
this.baseURL=baseURL;
}
#Provides
#Singleton
SharedPreferences providesSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
#Provides
#Singleton
Cache provideOkHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
#Provides
#Singleton
Gson provideGson(){
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
#Provides
#Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
return client.build();
}
#Provides
#Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseURL)
.client(okHttpClient)
.build();
return retrofit;
}
#Provides
#Singleton
GetTypeAhead provideRGetTypeAhead( Retrofit retrofit) {
return retrofit.create(GetTypeAhead.class);
}
}
My app module
#Module
public class AppModule {
Application mApplication;
public AppModule(Application application) {
mApplication = application;
}
#Provides
#Singleton
Application providesApplication() {
return mApplication;
}
}
my component
#Singleton
#Component(modules={AppModule.class, NetModule.class})
public interface NetComponent {
void inject(MainActivity dataSource);
}
MyTopLevel application component for dagger initialization
public class MyApp extends Application {
private NetComponent netComponent;
#Override
public void onCreate() {
super.onCreate();
// Dagger%COMPONENT_NAME%
netComponent = DaggerNetComponent.builder()
// list of modules that are part of this component need to be created here too
.appModule(new AppModule(this)) // This also corresponds to the name of your module: %component_name%Module
.netModule(new NetModule("https://typeahead.random.com/"))
.build();
// If a Dagger 2 component does not have any constructor arguments for any of its modules,
// then we can use .create() as a shortcut instead:
// mNetComponent = com.codepath.dagger.components.DaggerNetComponent.create();
}
public NetComponent getNetComponent() {
return netComponent;
}
}
My activity //here di is working fine
public class MainActivity extends AppCompatActivity {
#Inject
Retrofit retrofit;
CompositeDisposable compositeDisposable = new CompositeDisposable();
private ArrayList<String> arr = new ArrayList<>();
SearchViewModel searchViewModel;
AutoCompleteTextView textView;
ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
searchViewModel = ViewModelProviders.of(this).get(SearchViewModel.class);
((MyApp)getApplication()).getNetComponent().inject(this);
Observable<String> inputObservable = setUpTextObservable();
textView= (AutoCompleteTextView) findViewById(R.id.productSearchText);
adapter = new ArrayAdapter<>(this,
android.R.layout.simple_dropdown_item_1line);
Log.v("++++++++++++++++++++++",retrofit.toString());
compositeDisposable.add(searchTextObserver(inputObservable));
}
.....}
My other class //here injection is not working
public class RemoteDataSource {
#Inject
GetTypeAhead getTypeAhead;
Single<TypeAhead> getTypeAhead(String input){
return getTypeAhead.getTypeAhead(input).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
}
what am i doing wrong here. Guide me to somelink if i m lacking some concept
If you use property injection follow next step. In NetComponent add void inject(RemoteDataSource dataSource);
#Singleton
#Component(modules={AppModule.class, NetModule.class})
public interface NetComponent {
void inject(MainActivity dataSource);
void inject(RemoteDataSource dataSource);
}
In RemoteDataSource class define contructor and perform injection in it
class RemoteDataSource {
public RemoteDataSource() {
NetComponent netComponent = // TODO get your component
netComponent.inject(this)
}
}
You can find additional info in Dagger Documentation.
Note that it's not the best way to use property injection in your way. I advise you use constructor injection that decribed more in discussion
To add your RemoteDataSource class to graph, you need to add #Inject annotation to its constructor and anotate class with scope :
#Singleton
public class RemoteDataSource {
GetTypeAhead getTypeAhead;
#Inject
RemoteDataSource(GetTypeAhead getTypeAhead){
this.getTypeAhead = getTypeAhead;
}
//...
}
}
I'm trying to implement MVP pattern using Dagger2. While I successfully did di for application, activities and for fragments (I'm not sure I did well with fragments). Actually after reading guides I still don't understand how it works.
I created RetrofitModiule:
#Module
public class RetrofitModule {
String mBaseUrl;
...
#Provides
#Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(mBaseUrl)
.client(okHttpClient)
.build();
}
Then I declare module in MyApplicationComponent:
#Singleton
#Component(
modules = {
MyApplicationModule.class,
RetrofitModule.class
}
)
public interface MyApplicationComponent {
void inject(MyApplication myApplication);
Retrofit provideRetrofit();
}
Actually I don't understand why I have to use Inject here; Because there nothing to actually inject into MyApplication:
public class MyApplication extends Application {
private MyApplicationComponent mMyApplicationComponent;
...
#Override
public void onCreate() {
super.onCreate();
mMyApplicationComponent = DaggerMyApplicationComponent.builder()
.retrofitModule(new RetrofitModule("https://androidtutorialpoint.com"))
.build();
mMyApplicationComponent.inject(this);
}
}
I use Retrofit only in LoaderActivityPresenterImpl which injected to LoaderActivity;
#ActivityScoped
public class LoaderActivityPresenterImpl implements LoaderActivityPresenter {
private LoaderActivityView mView;
private #ActivityContext Context mContext;
private Retrofit mRetrofit;
#Inject
public LoaderActivityPresenterImpl(LoaderActivityView view, #ActivityContext Context context, Retrofit retrofit) {
mView = view;
mContext = context;
mRetrofit = retrofit;
}
}
LoaderActivity:
public class LoaderActivity extends BaseActivity implements LoaderActivityView{
#Inject LoaderActivityPresenter mPresenter;
private LoaderActivityComponent mLoaderActivityComponent;
#Override
protected void setupActivityComponent(MyApplicationComponent myApplicationComponent) {
mLoaderActivityComponent = DaggerLoaderActivityComponent.builder()
.myApplicationComponent(myApplicationComponent)
.loaderActivityModule(new LoaderActivityModule(this, this, myApplicationComponent.provideRetrofit()))
.build();
mLoaderActivityComponent.inject(this);
}
LoaderComponent:
#ActivityScoped
#Component(
modules = LoaderActivityModule.class,
dependencies = MyApplicationComponent.class
)
public interface LoaderActivityComponent {
void inject(LoaderActivity loaderActivity);
}
LoaderActivityModule:
#Module
public class LoaderActivityModule {
private Retrofit mRetrofit;
private LoaderActivityView mLoaderActivityView;
private #ActivityContext Context mContext;
public LoaderActivityModule(LoaderActivityView loaderActivityView, #ActivityContext Context context, Retrofit retrofit) {
mLoaderActivityView = loaderActivityView;
mContext = context;
mRetrofit = retrofit;
}
#Provides
LoaderActivityView provideLoaderActivityView() {
return mLoaderActivityView;
}
#Provides
public #ActivityContext Context provideActivityContext() {
return mContext;
}
#Provides
public LoaderActivityPresenter LoaderActivityPresenterImpl() {
return new LoaderActivityPresenterImpl(mLoaderActivityView, mContext, mRetrofit);
}
}
LoaderActivityComponent:
#ActivityScoped
#Component(
modules = LoaderActivityModule.class,
dependencies = MyApplicationComponent.class
)
public interface LoaderActivityComponent {
void inject(LoaderActivity loaderActivity);
}
I get this error:
java.lang.RuntimeException: Unable to create application com.xxxxx.application.MyApplication: java.lang.IllegalStateException: com.xxxxx.di.modules.MyApplicationModule must be set;
I can probably forget to show some classes, so feel free to ask me.
As the error says, you forget to add your ApplicationModule to your component.
By the way, I highly suggest you take a look at AndroidInjector, to avoid creating this Android component hierarchy manually.
public class MyApplication extends Application {
private MyApplicationComponent mMyApplicationComponent;
...
#Override
public void onCreate() {
super.onCreate();
mMyApplicationComponent = DaggerMyApplicationComponent.builder()
.myApplicationModule()
.retrofitModule(new RetrofitModule("https://androidtutorialpoint.com"))
.build();
mMyApplicationComponent.inject(this);
This is MVP Module
#PosterFragmentScope
#Module
public class PosterFragmentModule {
PosterFragmentMVP.View view;
Context mContext;
public PosterFragmentModule(PosterFragmentMVP.View view,Context mContext) {
this.view = view;
this.mContext = mContext;
}
#PosterFragmentScope
#Provides
public PosterFragmentPresenter providePresenter(PosterFragmentMVP.View view , PosterFragmentMVP.InterActor interActor){
return new PosterFragmentPresenter(view,interActor,mContext);
}
#PosterFragmentScope
#Provides
public PosterFragmentMVP.View provideView(){
return view;
}
#PosterFragmentScope
#Provides
public PosterFragmentInteractor provideInteractor(APIServices.TMDbPopular tmDbPopular,APIServices.TMDbServiceTopRated tmDbServiceTopRated){
return new PosterFragmentInteractor(tmDbPopular,tmDbServiceTopRated);
}
#PosterFragmentScope
#Provides
public PosterFragmentMVP.Presenter providePresenterInterface(APIServices.TMDbPopular tmDbPopular,APIServices.TMDbServiceTopRated tmDbServiceTopRated){
return providePresenter(view,provideInteractor(tmDbPopular,tmDbServiceTopRated));
}
#Provides
#PosterFragmentScope
Context provideContext() {
return mContext;
}
#Provides
#PosterFragmentScope
public PosterAdapter provideAdapter(){
return new PosterAdapter(mContext,new ArrayList<Movie>());
}
#Provides
#PosterFragmentScope
public APIServices.TMDbPopular provideTmDbPopular(Retrofit retrofit){
return retrofit.create(APIServices.TMDbPopular.class);
}
#Provides
#PosterFragmentScope
public APIServices.TMDbServiceTopRated provideTmDbServiceTopRated(Retrofit retrofit){
return retrofit.create(APIServices.TMDbServiceTopRated.class);
}
}
This API Module
#Module
#Singleton
public class APIModule {
private final String BASEURL = "https://api.themoviedb.org/";
#Provides
#Singleton
public OkHttpClient provideClinet (){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return new OkHttpClient.Builder().addInterceptor(interceptor).build();
}
#Provides
#Singleton
public Retrofit provideRetrofit(String base_url, OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(base_url)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
#Provides
public APIServices.TrailersService provideTrailersService() {
return provideRetrofit(BASEURL, provideClinet()).create(APIServices.TrailersService.class);
}
#Provides
public APIServices.ReviewsService provideReviewsService() {
return provideRetrofit(BASEURL, provideClinet()).create(APIServices.ReviewsService.class);
}
This Is APP Component
#Component(modules = {RoomModule.class,APIModule.class})
#Singleton
public interface APPComponent {
PosterFragmentComponent plus(PosterFragmentModule posterFragmentModule);
MovieDetailComponent plus(MovieDetailFragmentModule movieDetailFragmentModule);
}
This Is poster Component
#Subcomponent(modules =PosterFragmentModule.class)
#PosterFragmentScope
public interface PosterFragmentComponent {
void inject(PosterFragment posterFragment);
}
When i make this give me that error
Error:(19, 8) error: [com.example.ali.moviedb.DI.Components.PosterFragmentComponent.inject(com.example.ali.moviedb.Views.PosterFragment)] java.lang.String cannot be provided without an #Inject constructor or from an #Provides-annotated method. java.lang.String is injected at com.example.ali.moviedb.DI.Modules.APIModule.provideRetrofit(base_url, …) retrofit2.Retrofit is injected at com.example.ali.moviedb.DI.Modules.PosterFragmentModule.provideTmDbPopular(retrofit) com.example.ali.moviedb.Contracts.APIServices.TMDbPopular is injected at com.example.ali.moviedb.DI.Modules.PosterFragmentModule.providePresenterInterface(tmDbPopular, …) com.example.ali.moviedb.Contracts.PosterFragmentMVP.Presenter is injected at com.example.ali.moviedb.Views.PosterFragment.presenter com.example.ali.moviedb.Views.PosterFragment is injected at com.example.ali.moviedb.DI.Components.PosterFragmentComponent.inject(posterFragment)
Looks like you're not injecting Retrofit instance directly so shouldn't need that provides (specific error seems to be that it can't find something to inject for base_url parameter). You should be able to change to something like:
public Retrofit createRetrofit(String base_url, OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(base_url)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
#Provides
public APIServices.TrailersService provideTrailersService() {
return createRetrofit(BASEURL, provideClinet()).create(APIServices.TrailersService.class);
}
#Provides
public APIServices.ReviewsService provideReviewsService() {
return createRetrofit(BASEURL, provideClinet()).create(APIServices.ReviewsService.class);
}
I solved this by Make My API Module like this
#Module
#Singleton
public class APIModule {
private final String BASEURL = "https://api.themoviedb.org/";
#Provides
#Singleton
public OkHttpClient provideClinet (){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return new OkHttpClient.Builder().addInterceptor(interceptor).build();
}
#Provides
#Singleton
public Retrofit provideRetrofit(OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(BASEURL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
Is There best solution for that
Can someone help me to resolve this issue, I'm trying to add dagger2 to my application getting this scope issue.
Error:(14, 1) error: com.bmx.presentation.authentication.login.LoginComponent depends on scoped components in a non-hierarchical scope ordering:
#com.bmx.di.scope.ActivityScope com.bmx.data.remote.AuthenticationRepositoryComponent
#com.bmx.di.scope.ActivityScope com.bmx.presentation.authentication.login.LoginComponent
#Module
public class AppModule {
private Application mApplication;
public AppModule(Application mApplication) {
this.mApplication = mApplication;
}
#Provides
#Singleton
Application provideApplication() {
return mApplication;
}
#Provides
#Singleton
public Resources provideResources(Context context) {
return context.getResources();
}
}
---------------------------------
#Module
public class NetModule {
String mBaseUrl;
public NetModule(String mBaseUrl) {
this.mBaseUrl = mBaseUrl;
}
#Provides
#Singleton
Cache provideHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024;
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
#Provides
#Singleton
Gson provideGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
#Provides
#Singleton
OkHttpClient provideOkhttpClient(Cache cache) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
return client.build();
}
#Provides
#Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(mBaseUrl)
.client(okHttpClient)
.build();
}
#Provides
#Singleton
public BmxRestService provideBmxRestService(Retrofit retrofit) {
return retrofit.create(BmxRestService.class);
}
}
---------------------------------------------
#Singleton
#Component(modules = {NetModule.class,AppModule.class})
public interface ApiComponent {
BmxRestService getBmxRestService();
Application getApplication();
}
-----------------------------------------------------
public interface AuthenticationRepository {
Observable<List<UserProfile>> doLogin(String userName, String password);
Observable<List<UserProfile>> doSignUp(String firstName, String lastName,String email,String password);
}
--------------------------------------------------------------
public class AuthenticationRepositoryImpl implements AuthenticationRepository {
private BmxRestService BmxRestService;
#Inject
public AuthenticationRepositoryImpl(#NonNull final BmxRestService BmxRestService) {
this.BmxRestService = BmxRestService;
}
//implementation
}
-------------------------------------------
#ActivityScope
#Module
public class AuthenticationRepositoryModule {
#Provides
#ActivityScope
public AuthenticationRepository provideAuthenticationRepository(BmxRestService BmxRestService) {
return new AuthenticationRepositoryImpl(BmxRestService);
}
}
-----------------------------
#ActivityScope
#Component(modules = {AuthenticationRepositoryModule.class},dependencies = ApiComponent.class)
public interface AuthenticationRepositoryComponent {
AuthenticationRepository getAuthenticationRepository();
}
-----------------------------------
#Module
public class LoginPresenterModule {
private final LoginContract.View mView;
public LoginPresenterModule(LoginContract.View mView) {
this.mView = mView;
}
#Provides
#ActivityScope
LoginContract.View provideLoginContractView(){
return this.mView;
}
}
----------------------------------------------
#ActivityScope
#Component(dependencies = AuthenticationRepositoryComponent.class, modules = LoginPresenterModule.class)
public interface LoginComponent {
void inject(LoginActivity activity);
}
----------------------------------------
public class LoginPresenter extends BasePresenter<LoginContract.View> implements LoginContract.Presenter{
private Scheduler mainScheduler, ioScheduler;
private AuthenticationRepository mAuthenticationRepository;
#Inject
public LoginPresenter(#NonNull final AuthenticationRepository authenticationRepository,#NonNull final LoginContract.View loginView) {
super(loginView);
this.mView =loginView;
this.mAuthenticationRepository =authenticationRepository;
this.mainScheduler = AndroidSchedulers.mainThread();
this.ioScheduler = Schedulers.io();
}
//implementation
}
----------------------
public class LoginActivity extends AppCompatActivity implements LoginContract.View {
private static final String TAG = "LoginActivity";
#Inject
LoginPresenter mLoginPresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
}
-----------------------
public class BmxApp extends Application {
private ApiComponent apiComponent;
#Override
public void onCreate() {
super.onCreate();
initializeNetComponent();
}
private void initializeNetComponent() {
apiComponent = DaggerApiComponent.builder().netModule(new NetModule(BuildConfig.BASEURL)).appModule(new AppModule(this)).build();
}
public ApiComponent getApiComponent() {
return apiComponent;
}
}
---------------
#Documented
#Scope
#Retention(RetentionPolicy.RUNTIME)
public #interface ActivityScope {
}
I am trying to use Dagger 2 for instantiating a Retrofit interface. The CloudContactDataStore class injects the RestClient and calls its methods.
When I instantiate a CloudContactDataStore object, its RestClient attribute has null value.
public class CloudContactDataStore implements ContactDataStore {
#Inject RestClient restClient;
public CloudContactDataStore() {
this.initializeInjector();
}
private void initializeInjector() {
DaggerApiComponent.builder()
.apiModule(new ApiModule())
.build()
.inject(this);
}
#Override
public Observable<ContactEntity> contactLogin(String contactId) {
return this.restClient.contactLogin(contactId); // Here restClient is null!
}
}
Here is how I create the Dagger Module and Component:
#Singleton
#Component(modules = ApiModule.class)
public interface ApiComponent {
void inject(ContactDataStore contactDataStore);
}
#Module
public class ApiModule {
#Provides public RestClient provideRestClient(ApiService apiService) {
return new RestClientImpl(apiService);
}
#Provides public ApiService provideApiService(RestAdapter restAdapter) {
return restAdapter.create(ApiService.class);
}
#Provides public RestAdapter provideRestAdapter() {
return RestApiAdapter.getInstance();
}
}
Now, the RestClient class and its implementation:
public interface RestClient {
Observable<ContactEntity> contactLogin(String contactId);
}
public class RestClientImpl implements RestClient {
ApiService apiService;
#Inject
public RestClientImpl(ApiService apiService) {
this.apiService = apiService;
}
#Override
public Observable<ContactEntity> contactLogin(String contactId) {
return apiService.login(contactId, "xxx-xxx-xxx");
}
}
The ApiService interface is the Retrofit interface:
public interface ApiService {
String API_BASE_URL = "http://192.168.1.2";
#POST("/login")
Observable<ContactEntity> login(#Body String id, #Header("Key") String key);
}
And finally, the RestApiAdapter:
public class RestApiAdapter {
private static RestAdapter sharedInstance = null;
public static RestAdapter getInstance() {
if (sharedInstance == null){
sharedInstance = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(ApiService.API_BASE_URL)
.build();
}
return sharedInstance;
}
}
Can anyone see what I am doing wrong?
Thanks!
This has the same problem as in Why Dagger inject is not working but component.getObject yes and the same solution. That is you need to either change your inject(ContactDataStore) method to inject(CloudContactDataStore) so it can see the field that needs injecting, or you need to add a method in ContactDataStore that allows you to inject the method yourself.