2016-09-28 1 views
6

Ich versuche inject dependencies in meine App. Alles funktioniert gut, bis ich versuchte, Realm in meine Service Klasse zu injizieren. Ich fing an, IllegalStateException zu erhalten, das offensichtlich verursacht wird, indem ich auf Realm von einem Thread zuging, das es hergestellt wurde. Also, das ist die Struktur meiner Dependency InjectionAbhängigkeit Injektion in den Dienst

Die AppModule

@Module 
public class AppModule { 

    MainApplication mainApplication; 

    public AppModule(MainApplication mainApplication) { 
     this.mainApplication = mainApplication; 
    } 

    @Provides 
    @Singleton 
    MainApplication getFmnApplication() { 
     return mainApplication; 
    } 
} 

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

Die AppComponent

@Singleton 
@Component(modules = { 
     AppModule.class, 
     RequestModule.class 
}) 
public interface MainAppComponent { 

    void inject(SyncService suncService); 
} 

Die Anwendungsklasse

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

Dies geschieht nur, wenn ich es von einem Service class bin Aufruf Aber es wurde mit dem Anwendungskontext erstellt. Warum wirft er eine IllegalStateException

Die Service-Klasse

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

Jede Hilfe zu, was ich falsch mache zu machen Realm Wurf IllegalStateException würde geschätzt. Dank

Antwort

6
@Inject GeneralAPIHandler generalAPIHandler; 

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

Und deshalb

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

Dieser Code wird auf dem UI-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(); 

Dieser Code läuft auf dem IntentService Hintergrund-Thread

Yo Du würdest auch die Realm-Instanz nicht schließen, obwohl du sowieso auf einem nicht-schleifenden Hintergrund-Thread stehst, also hattest du einen Gefallen, indem du abgestürzt bist.


Lösung, sollten Sie Realm-Instanz in onHandleIntent(), und schließen Sie es in finally { am Ende der Ausführung erhalten.


Man könnte sagen, „aber dann, wie werde ich meine Konstruktorargument verspotten“, ist die Antwort eine Klasse wie

@Singleton 
public class RealmFactory { 
    @Inject 
    public RealmFactory() { 
    } 

    public Realm create() { 
     return Realm.getDefaultInstance(); 
    } 
} 
+1

Vielen Dank, dass Sie diesen Teil gelöscht haben. '@Override public void onCreate() { super.onCreate(); ((Hauptanwendung) getApplicationContext()). GetMainAppComponent(). Inject (this); } ' –

1

ein Reich Instanz muss nur aus dem Thread zugegriffen werden es in erstellt wird.

Ihre Absicht Dienst läuft in einem Hintergrund-Thread. Ihr Reich wurde auf dem Haupt-Thread wahrscheinlich erstellt

+0

verwende ich weiß, dass das, was das obwohl gemeint. Also, sagen Sie, dass sich der 'ApplicationContext' auf' MainThread' von dem in 'BackgroundThread' unterscheidet? –

+2

Nein, er bedeutet, dass 'onCreate()' auf dem UI-Thread ausgeführt wird und 'onHandleIntent()' auf dem Hintergrundthread steht – EpicPandaForce

Verwandte Themen