2016-11-08 3 views
0

RetrofitのオブジェクトをRealmに直接保存しようとしていますが、「不正なスレッドからのレルムアクセス」エラーが常に発生しています。不正なスレッドからのレルムアクセスAndroid Retrofit2 RxJava

これは私のコードです:

public class RestaurantRepositoryRetrofit implements IRestaurantRepository { 

private RestaurantApi mApi; 
private Realm realm; 
private IMapper<RestaurantJson,Restaurant> mRestaurantMapper; 

public RestaurantRepositoryRetrofit(IMapper<RestaurantJson, Restaurant> restaurantMapper) { 
    mApi = ApiProvider.getApi().create(RestaurantApi.class); 
    mRestaurantMapper = restaurantMapper; 
    // Get a Realm instance for this thread 
    realm = Realm.getDefaultInstance(); 
**} 
@Override 
public Observable<Restaurant> getRestaurantById(String restaurantId) {** 

    return mApi.getRestaurantById(restaurantId) 
      .map(new Func1<RestaurantJson, Restaurant>() { 
       @Override 
       public Restaurant call(RestaurantJson restaurantJson) { 
        realm.executeTransaction(new Realm.Transaction() { 
         @Override 
         public void execute(Realm realm) { 

          realm.copyToRealm(restaurantJson); 
         } 
        }); 
        return mRestaurantMapper.transform(restaurantJson); 
       } 
      }); 
    } 
} 

答えて

1

Realmインスタンスは、APIの結果を受け取るバックグラウンドスレッドで開く必要があります。

return mApi.getRestaurantById(restaurantId) 
     .map(new Func1<RestaurantJson, Restaurant>() { 
      @Override 
      public Restaurant call(RestaurantJson restaurantJson) { 
       try(Realm realm = Realm.getDefaultInstance()) { 
        realm.executeTransaction(new Realm.Transaction() { 
         @Override 
         public void execute(Realm realm) { 
          realm.copyToRealm(restaurantJson); 
         } 
        }); 
        return mRestaurantMapper.transform(restaurantJson); 
       } 
      } 
     }); 

あなたが管理RealmObjectを返すつもりならば、あなたが保存したプロキシからIDをマップして、IDを使用してレルムのUIスレッドインスタンスとメインスレッドとクエリに観察する必要がありますが。

1

realm = Realm.getDefaultInstance();は、オブジェクトが作成されたスレッドのインスタンスを返します。しかし、Observable.map()は、オブザーバブルがメッセージを送信するスレッドで呼び出されます。

観察できるが、改修から来ているので、これは2つのオプションを指定できますCallAdapterが、それはObservable.subscribeがコールされたスレッド上で実行されるスケジューラを指定せずに作成された場合

  1. CallAdapterが特定のスケジューラで作成された場合、そのスレッドで実行されます。

適用されるオプションが、オブジェクトが作成されたものと同じスレッドでない場合、「不正なスレッドからの領域アクセス」エラーがスローされます。

0

Realm is thread confinedこれは、Realmオブジェクトとrealmインスタンスを同じスレッド上で参照していることを確認する必要があることを意味します。たとえばrealm::executeTransaction()と同じスレッドでrealmインスタンスを呼び出したことを確認するには、のスケジューリングメソッドobserveOn()を使用することをお勧めします。

関連する問題