0

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

Nari
  • 333
  • 5
  • 13
  • If you use property injection, you need manually trigger something like that `NetComponent.inject(this)` in `RemoteDataSource` contructor. Do you perform that? Actually don't see `void inject(RemoteDataSource dataSource);` in your `NetComponent` interface. – ConstOrVar Oct 12 '18 at 14:09
  • @ConstOrVar can you guide me to any resource.or can you give me a small snippet so that i can better understand – Nari Oct 12 '18 at 14:37

2 Answers2

0

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

ConstOrVar
  • 2,025
  • 1
  • 11
  • 14
  • "// TODO get your component " what should be done here? – Nari Oct 12 '18 at 15:04
  • You need to get your component. May be it's singleton or another way – ConstOrVar Oct 12 '18 at 15:09
  • `DaggerNetComponent.builder() .netModule(new NetModule("https://typeahead.target.com/")) .build() ` like this? – Nari Oct 12 '18 at 15:38
  • Post your code where you use `RemoteDataSource` and I will try to help you. Do you use `Presenter` or `ViewModel` or simply use `RemoteDataSource` in `Activity`? – ConstOrVar Oct 12 '18 at 18:31
  • This is my viewmodel `public class SearchViewModel extends ViewModel { SearchRepository searchRepository =new SearchRepositoryImpl(); Single getTypeAhead(String input ){ return searchRepository.getTypeAhead(input); } }` – Nari Oct 12 '18 at 18:51
  • I am calling remote data source from here . `public class SearchRepositoryImpl implements SearchRepository { RemoteDataSource remoteDataSource = new RemoteDataSource(); @Override public Single getTypeAhead(String input) { return remoteDataSource.getTypeAhead(input); } } ` – Nari Oct 12 '18 at 18:52
0

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;
    }
    //...
  }
}
Samuel Eminet
  • 4,647
  • 2
  • 18
  • 32