Inyección de dependencia en servicio

Estoy tratando de inject dependencies en mi aplicación. Todo funciona bien hasta que intento inyectar Realm en mi clase de Service . Empecé a obtener IllegalStateException que obviamente es causada por mi acceso a Realm de un Thread que se creó. Por lo tanto, esta es la estructura de mi Dependency Injection

El AppModule

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

El 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()); } } 

El AppComponent

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

Clase de Aplicación

 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 } } 

Esto sólo ocurre cuando lo llamo de una Service class pero, se creó con el contexto de aplicación. ¿Por qué está lanzando una IllegalStateException

La clase de servicio

 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's 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){} }) } } 

Cualquier ayuda en lo que estoy haciendo mal para hacer el lanzamiento del Realm IllegalStateException sería apreciada. Gracias

 @Inject GeneralAPIHandler generalAPIHandler; @Override public void onCreate() { super.onCreate(); ((MainApplication) getApplicationContext()).getMainAppComponent().inject(this); } 

Y por lo tanto

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

Este código se ejecuta en el subproceso de interfaz de usuario


 @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(); 

Este código se ejecuta en el subproceso de fondo IntentService

Usted también no estaría cerrando la instancia de Realm a pesar de estar en un hilo de fondo no de bucle de todos modos, por lo que le hizo un favor por estrellarse.


Solución, debe obtener la instancia Realm en onHandleIntent() y cerrarla finally { al final de la ejecución.


Podrías decir, "pero entonces ¿cómo me burlaré de mi argumento Constructor", la respuesta es usar una clase como

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

una instancia de reino debe tener acceso sólo desde el subproceso en el que se creó.

El servicio de intenciones se ejecuta en un subproceso de fondo. Su reino probablemente fue creado en el hilo principal

  • ¿Cuál es la manera más fácil de mantener una base de datos sincronizada entre varios dispositivos iOS y Android?
  • Android: Realm + Retrofit - Serializar apiresponse
  • Error de acceso de realm de subproceso incorrecto al usar código compartido entre IntentService y AsyncTask (Android)
  • Realm.io de Android cómo sincronizar con el lado del servidor MySQL DB
  • Manera correcta de obtener el objeto Realm por su clave principal en Android Java
  • RealmResult consulta de nuevo
  • Reino: se cambió el orden de los registros
  • Llamando Realm.close () fuera de la actividad
  • Obtener cursor mediante la biblioteca Realm
  • Acceso al dominio desde un subproceso incorrecto Excepción mientras se envió una copia usando copyFromRealm
  • Acceso de dominio a través de subprocesos con rxjava y dagger2
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.