2016-09-28 22 views
6

私はinject dependenciesを私のアプリケーションに入れようとしています。私がServiceクラスにRealmを注入しようとするまで、すべてうまくいっています。私は明らかに私がRealmにアクセスしてIllegalStateExceptionを取得し始めました。Threadから作成されました。だから、これは私の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); 
} 
です

アプリケーションクラス

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

これは、それがアプリケーション・コンテキストを使用して作成された、私はService classからそれを呼んでいるときに起こる。しかし。なぜそれがサービスクラス

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

IllegalStateException

を投げている私はRealm投げIllegalStateExceptionを作ることが間違ってやって上の任意の助けいただければ幸いです。おかげ

答えて

6
​​

このコードは、UIスレッド上で実行されますので

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

このコードはIntentServiceのバックグラウンドスレッドで実行されます


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

ヨーとにかくループしていないバックグラウンドスレッドにもかかわらず、Realmのインスタンスを閉じていないので、クラッシュすることによってあなたに恩恵を受けました。


ソリューションは、あなたがonHandleIntent()でレルムインスタンスを取得し、実行の終了時にfinally {でそれを閉じる必要があります。


あなたは言うかもしれない、「しかし、その後、私は私のコンストラクタの引数を模擬する方法」、答えは、私はそれはそれはしかし何を意味するのか知っている

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

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

この部分をクリアしていただきありがとうございます。 @Override public void onCreate(){ super.onCreate(); ((MainApplication)getApplicationContext())。getMainAppComponent()。注射(これ); } ' –

1

レルムインスタンスは、それがで作成のスレッドからのみアクセスする必要がある。

あなたの意思サービスは、バックグラウンドスレッドで実行されます。あなたのレルムはおそらくメインスレッド上で作成された

+0

のようなクラスを使用しています。ですから、 'MainThread'の' ApplicationContext'が 'BackgroundThread'のものと異なっているとお考えですか? –

+2

いいえ、UIスレッドでonCreate()が実行され、バックグラウンドスレッドでonHandleIntent()が実行されていることを意味します。 – EpicPandaForce