Dependency Injection in a Service

I am trying to inject dependencies in my application. Everything worked fine until I tried to inject Realm into my Service class. I started getting an IllegalStateException , which is obviously due to the fact that I was IllegalStateException Realm from the Thread that was created. So this is the structure of my Dependency Injection

Appmodule

 @Module public class AppModule { MainApplication mainApplication; public AppModule(MainApplication mainApplication) { this.mainApplication = mainApplication; } @Provides @Singleton MainApplication getFmnApplication() { return mainApplication; } } 

RequestModule

 @Module public class RequestModule { @Provides @Singleton Retrofit.Builder getRetrofitBuilder() { return new Retrofit.Builder() .baseUrl(BuildConfig.HOST) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(CustomGsonParser.returnCustomParser())); } @Provides @Singleton OkHttpClient getOkHttpClient() { return new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC)) .connectTimeout(30000, TimeUnit.SECONDS) .readTimeout(30000, TimeUnit.SECONDS).build(); } @Provides @Singleton Retrofit getRetrofit() { return getRetrofitBuilder().client(getOkHttpClient()).build(); } @Provides @Singleton ErrorUtils getErrorUtils() { return new ErrorUtils(); } @Provides @Singleton MainAPI getMainAPI() { return getRetrofit().create(MainAPI.class); } // Used in the Service class @Provides @Singleton GeneralAPIHandler getGeneralAPIHandler(MainApplication mainApplication) { return new GeneralAPIHandler(mainApplication, getMainAPIHandler(), getErrorUtils()); } } 

AppComponent

 @Singleton @Component(modules = { AppModule.class, RequestModule.class }) public interface MainAppComponent { void inject(SyncService suncService); } 

Application class

 public class MainApplication extends Application { private MainAppComponent mainAppComponent; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } @Override public void onCreate() { super.onCreate(); mainAppComponent = DaggerMainAppComponent.builder() .appModule(new AppModule(this)) .requestModule(new RequestModule()) .build(); } public MainAppComponent getMainAppComponent() { return mainAppComponent; } } 

GeneralAPIHandler

 public class GeneralAPIHandler { private static final String TAG = "GeneralAPIHandler"; private MainAPI mainAPI; private Realm realm; private ErrorUtils errorUtils; private Context context; public GeneralAPIHandler() { } public GeneralAPIHandler(MainApplication mainApplication, MainAPI mainAPI, ErrorUtils errorUtils) { this.mainAPI = mainAPI; this.realm = RealmUtils.getRealmInstance(mainApplication.getApplicationContext()); this.errorUtils = errorUtils; this.context = mainApplication.getApplicationContext(); } public void sendPayload(APIRequestListener apiRequestListener) { List<RealmLga> notSentData = realm.where(RealmLga.class).equalTo("isSent", false).findAll(); <-- This is where the error comes from .... Other code here } } 

This only happens when I call it from the Service class But it was created using the application context. Why does he throw an IllegalStateException

Class of service

 public class SyncService extends IntentService { @Inject GeneralAPIHandler generalAPIHandler; @Override public void onCreate() { super.onCreate(); ((MainApplication) getApplicationContext()).getMainAppComponent().inject(this); } /** * Creates an IntentService. Invoked by your subclass constructor. */ public SyncService() { super("Sync"); } @Override protected void onHandleIntent(Intent intent) { sendInformations(); } private void sendInformations() { generalAPIHandler.sendPayload(new APIRequestListener() { @Override public void onError(APIError apiError){} @Override public void didComplete(WhichSync whichSync){} }) } } 

Any help on what I'm doing wrong with a Realm throw IllegalStateException would be IllegalStateException appreciated. Thanks

+6
source share
2 answers
 @Inject GeneralAPIHandler generalAPIHandler; @Override public void onCreate() { super.onCreate(); ((MainApplication) getApplicationContext()).getMainAppComponent().inject(this); } 

And therefore

 public GeneralAPIHandler(MainApplication mainApplication, MainAPI mainAPI, ErrorUtils errorUtils) { this.mainAPI = mainAPI; this.realm = RealmUtils.getRealmInstance(mainApplication.getApplicationContext()); // <-- 

This code runs in a user interface thread


 @Override protected void onHandleIntent(Intent intent) { sendInformations(); } private void sendInformations() { generalAPIHandler.sendPayload(new APIRequestListener() { .... public void sendPayload(APIRequestListener apiRequestListener) { List<RealmLga> notSentData = realm.where(RealmLga.class).equalTo("isSent", false).findAll(); 

This code runs in an IntentService background thread

You would also not close the Realm instance, even though it wasn’t in the loop background thread anyway, so that helped you crash.


Solution, you should get a Realm instance in onHandleIntent() and close it in finally { at the end of execution.


You could say, "But then, as I mock the constructor argument," the answer uses a class like

 @Singleton public class RealmFactory { @Inject public RealmFactory() { } public Realm create() { return Realm.getDefaultInstance(); } } 
+6
source

an instance of a region should only be accessible from the stream that it created.

Your intentions service runs in the background thread. Your area was probably created in the main thread

+1
source

All Articles