2

I want to inject a Retrofit object directly into my MyRepository class but I always get a NullPointerException. This is what I have tried.

This is my AppModule class:

@Module
public class AppModule {
    @Singleton
    @Provides
    static Retrofit provideRetrofitInstance(){
        return new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
}

And this is my view model class:

public class MyViewModel extends AndroidViewModel {
    LiveData<Data> myLiveData;

    MyViewModel(Application application, City city) {
        super(application);
        myLiveData = myRepository.addDataToLiveData(city);
    }

    LiveData<Data> getLiveData() {
        return myLiveData;
    }
}

And this is my repository class where I want to inject Retofit:

public class MyRepository {
    private String myTex;
    @Inject
    private Retrofit retrofit;

    public MyRepository(String myText) {
        this.myText = myText;
    }

    LiveData<Data> addDataToLiveData(City city) {
        //Make api call using retrofit
    }
}

Edit:

This is how I instantiate my ViewModel in my activity class:

MyRepository repository = new MyRepository("MyText");
Application application = activity.getApplication();
MyViewModelFactory factory = new MyViewModelFactory(application, repository);
MyViewModel viewModel = ViewModelProviders.of(this, factory).get(MyViewModel.class);
Lilian Sorlanski
  • 405
  • 1
  • 3
  • 15
  • How are you injecting the retrofit instance? Are you calling `inject(this)` somewhere in your repository? Is your Repository injectable itself? In which case you could use constructor injection. – Francesc Jul 22 '19 at 16:16
  • "How are you injecting the retrofit instance?" using @Inject annotation. "Are you calling inject(this) somewhere in your repository?" No, I'm not. How can I do that? "Is your Repository injectable itself?" How I check that out? "In which case you could use constructor injection." How? – Lilian Sorlanski Jul 22 '19 at 16:18

1 Answers1

2

Making your Repository injectable is the simplest solution, which also allows you to inject it where it's used, in your ViewModels or Interactors:

@Singleton
public class MyRepository {

    private Retrofit retrofit;

    @Inject
    public MyRepository(Retrofit retrofit) {
        this.retrofit = retrofit;
    }

    LiveData<Data> addDataToLiveData(City city) {
        //Make api call using retrofit
    }
}

Edit: you can either provide the text via Dagger and inject that in your constructor, like this

@Inject
public MyRepository(String myText, Retrofit retrofit)

Note that you'd need to use @Named or @Qualifier for your string.

Alternatively, you can inject your repository calling inject(this), the syntax depends on how you setup Dagger

somehowGetDaggerComponent().inject(this)

I strongly suggest you go with the 1st solution.

Francesc
  • 25,014
  • 10
  • 66
  • 84
  • Please check my updated question. I already have a constructor. Sorry for not providing all the data from the beginning. – Lilian Sorlanski Jul 22 '19 at 16:31
  • Where should I add `@Named` or `@Qualifier` annotations? – Lilian Sorlanski Jul 22 '19 at 16:48
  • Where you provide the string , in the dagger module. See this: https://stackoverflow.com/questions/18099909/dagger-inject-named-strings – Francesc Jul 22 '19 at 16:49
  • I more confused now. I my `ViewModel` class, I construct a new object of my `MyRepository` class using `new` keyword. And now Android Studio complaines that I need to pass to the constructor a `Retrofit` object which I don't have there. I only have the string value. I just want to get injected only here. Beside that my String is dynamic and not static. – Lilian Sorlanski Jul 22 '19 at 16:50
  • You should not instantiate the repository with new, simply define it as an injected dependency in your viewmodel. – Francesc Jul 22 '19 at 17:05
  • I don't think this is so simple possible because in order to do that, I cannot use new keyword when constructing new object of my ViewModel class. – Lilian Sorlanski Jul 22 '19 at 17:12
  • That's the whole idea behind Dagger, you don't `new` dependencies, they get injected. The solution I highlighted is best practice, injecting your repository and having the repository dependencies themselves injected. – Francesc Jul 22 '19 at 17:17
  • Ok and that case, how can I instantiate in my `AppModule` class `MyRepository` object, so it can be injected? – Lilian Sorlanski Jul 22 '19 at 17:41
  • If you use constructor injection, like in my example, you don't need a module to instantiate your repository. – Francesc Jul 22 '19 at 18:07
  • Couldn't make it work, I'll try in another way. Voted-up for giving some new insights. Thanks – Lilian Sorlanski Jul 23 '19 at 06:02
  • Finally did it. Thanks you. – Lilian Sorlanski Jul 23 '19 at 22:00
  • Great, glad I could help. – Francesc Jul 23 '19 at 22:06
  • Maybe you can also help me with this: https://stackoverflow.com/questions/57173074/how-to-pass-a-string-to-a-viewmodel-repository-class-using-dagger2-in-android – Lilian Sorlanski Jul 23 '19 at 22:40