Reputation: 96
I am getting the following error while injecting ServiceGenerator.class
.
I am trying to inject ServiceGenerator.Class
from SignUpActivity.Class
mainly used for retrofit api services generation and depends on Retrofit.Builder
instance injected via Constructor injection that I have exposed from my ApplicationComponent.Class
.
SignUpActivity.Class
Public class SignUpActivity extends AppCompatActivity {
@Inject
ServiceGenerator serviceGenerator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
AppGenerator.getPresenterComponent().inject(this);
}
private void saveMobileNumberService(String mNumber) {
MobileNumberService mobileService =
serviceGenerator.createService(MobileNumberService.class);
..
}
}
ServiceGenerator.Class
public class ServiceGenerator {
private static Retrofit.Builder builder;
@Inject
public ServiceGenerator(Retrofit.Builder builder) {
this.builder = builder;
}
private static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
}
NetModule.class
@Module
public class NetModule {
....
@Singleton
@Provides
ServiceGenerator provideServiceGenerator(Retrofit.Builder builder) {
return new ServiceGenerator(builder);
}
@Singleton
@Provides
Retrofit.Builder provideRetrofitBuilder() {
Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
return retrofitBuilder;
}
}
ApplicationComponent.Class
@Singleton
@Component( modules = {AppModule.class, NetModule.class} )
public interface ApplicationComponent {
..
Retrofit.Builder exposeRetrofit();
ServiceGenerator exposeServiceGenerator();
}
PresentationComponent.Class
@PerActivity
@Component(modules = PresentationModule.class, dependencies = ApplicationComponent.class)
public interface PresenterComponent {
void inject (SignUpActivity signUpActivity);
}
Error
I am getting the following error at runtime.
UncaughtException: java.lang.ExceptionInInitializerError
at com.project.android.dependencies.modules.NetModule.provideServiceGenerator(NetModule.java:80)
at com.project.android.dependencies.modules.NetModule_ProvideServiceGeneratorFactory.get(NetModule_ProvideServiceGeneratorFactory.java:26)
at com.project.android.dependencies.modules.NetModule_ProvideServiceGeneratorFactory.get(NetModule_ProvideServiceGeneratorFactory.java:10)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.project.android.dependencies.components.DaggerApplicationComponent.exposeServiceGenerator(DaggerApplicationComponent.java:120)
at com.project.android.dependencies.components.DaggerPresenterComponent$com_project_android_dependencies_components_ApplicationComponent_exposeServiceGenerator.get(DaggerPresenterComponent.java:327)
at com.project.android.dependencies.components.DaggerPresenterComponent$com_project_android_dependencies_components_ApplicationComponent_exposeServiceGenerator.get(DaggerPresenterComponent.java:314)
at com.project.android.presentation.frameworks.onboarding.SignUpActivity_MembersInjector.injectMembers(SignUpActivity_MembersInjector.java:26)
at com.project.android.presentation.frameworks.onboarding.SignUpActivity_MembersInjector.injectMembers(SignUpActivity_MembersInjector.java:8)
at com.project.android.dependencies.components.DaggerPresenterComponent.inject(DaggerPresenterComponent.java:162)
at com.project.android.presentation.frameworks.onboarding.SignUpActivity.onCreate(SignUpActivity.java:79)
at android.app.Activity.performCreate(Activity.java:6119)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1112)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2491)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.access$800(ActivityThread.java:183)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1475)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5651)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'retrofit2.Retrofit retrofit2.Retrofit$Builder.build()' on a null object reference
at com.project.android.presentation.entrypoints.ServiceGenerator.<clinit>(ServiceGenerator.java:47)
at com.project.android.dependencies.modules.NetModule.provideServiceGenerator(NetModule.java:80)
at com.project.android.dependencies.modules.NetModule_ProvideServiceGeneratorFactory.get(NetModule_ProvideServiceGeneratorFactory.java:26)
at com.project.android.dependencies.modules.NetModule_ProvideServiceGeneratorFactory.get(NetModule_ProvideServiceGeneratorFactory.java:10)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
at com.project.android.dependencies.components.DaggerApplicationComponent.exposeServiceGenerator(DaggerApplicationComponent.java:120)
at com.project.android.dependencies.components.DaggerPresenterComponent$com_yangout_android_dependencies_components_ApplicationComponent_exposeServiceGenerator.get(DaggerPresenterComponent.java:327)
at com.project.android.dependencies.components.DaggerPresenterComponent$com_yangout_android_dependencies_components_ApplicationComponent_exposeServiceGenerator.get(DaggerPresenterComponent.java:314)
at com.project.android.presentation.frameworks.onboarding.SignUpActivity_MembersInjector.injectMembers(SignUpActivity_MembersInjector.java:26)
at com.project.android.presentation.frameworks.onboarding.SignUpActivity_MembersInjector.injectMembers(SignUpActivity_MembersInjector.java:8)
at com.project.android.dependencies.components.DaggerPresenterComponent.inject(DaggerPresenterComponent.java:162)
at com.project.android.presentation.frameworks.onboarding.SignUpActivity.onCreate(SignUpActivity.java:79)
at android.app.Activity.performCreate(Activity.java:6119)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1112)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2491)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.access$800(ActivityThread.java:183)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1475)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5651)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
I have exposed ServiceGenerator.Class
from ApplicationComponent.Class
and using PresentationComponent.Class
to inject from SignUpActivity.Class
. I am struggling to figure it out why I am getting this ExceptionInInitializerError
.
Upvotes: 1
Views: 5297
Reputation: 21487
There is a problem with your ServiceGenerator
(see comments):
public class ServiceGenerator {
private static Retrofit.Builder builder; //no!! use Dagger 2 @Singletons instead
@Inject
public ServiceGenerator(Retrofit.Builder builder) {
this.builder = builder;
}
private static Retrofit retrofit = builder.build(); //no! don't do this
public static <S> S createService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
}
The builder.build()
will be called before the Dagger 2 has provided the Builder
through the constructor hence the null pointer exception.
Maintaining a static reference to Retrofit
inside the ServiceGenerator
is probably not the solution you want. Dependency injection and roll-your-own static singleton caching are like elves and dwarves - they don't co-exist well.
In fact, the whole ServiceGenerator
is an extra layer of redirection that you probably don't need.
Why not configure Dagger 2 to provide Retrofit
instead of Retrofit.Builder
? Then you will not need to manage the instance of Retrofit yourself using the static field:
@Singleton
@Provides
Retrofit provideRetrofit() {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
.build();
}
Then if you still need the ServiceGenerator
it would be much simpler:
public class ServiceGenerator {
private final Retrofit retrofit;
@Inject
public ServiceGenerator(Retrofit retrofit) {
this.retrofit = retrofit;
}
public static <S> S createService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
}
Upvotes: 0