2015-05-19 14 views
12

Mam następujący modernizacyjny API:RETROFIT POST Realm obiekt

@POST("/payments")  
Observable<Response> saveCreditCard(@Body CreditCard creditCard) 

CreditCard jest RealmObject.

Kiedy próbuję użyć mojej metody API:

CreditCard card = realm.createObject(CreditCard.class); 
card.setWhateverField(...); 
... 
mApi.saveCreditCard(card) 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(...); 

pojawia się następujący błąd:

> retrofit.RetrofitError: com.fasterxml.jackson.databind.JsonMappingException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they where created. 
System.err﹕ at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:400) 
System.err﹕ at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220) 
System.err﹕ at retrofit.RestAdapter$RestHandler$1.invoke(RestAdapter.java:265) 
System.err﹕ at retrofit.RxSupport$2.run(RxSupport.java:55) 
System.err﹕ at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 
System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
System.err﹕ at retrofit.Platform$Android$2$1.run(Platform.java:142) 
System.err﹕ at java.lang.Thread.run(Thread.java:818) 
System.err﹕ Caused by: java.lang.AssertionError: com.fasterxml.jackson.databind.JsonMappingException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they where created. 

jestem przy założeniu, że RETROFIT robi serializacji do JSON na io() scheduler, stąd błąd.

Czy ktoś ma jakieś sugestie, w jaki sposób mogę przezwyciężyć problem toczenia Królestwa?

+0

Wygląda na to, że musisz mieć model dla Realm i drugi model dla Retrofit i mieć klasę "przekonwertować" te obiekty do siebie. – Divers

+0

Mamy ponad 50 modeli, więc to naprawdę nie jest rozwiązanie. –

+0

Rozumiem, ale duża szansa, że ​​to tylko rozwiązanie. – Divers

Odpowiedz

7

UPDATE

Realm dodatkowe podparcie dla oderwania przedmiotów za pomocą realm.copyFromRealm(yourObject, depthLevel)

CreditCard creditCard = realm.createObject(CreditCard.class); 
card.setWhateverField(...); 
... 

final int relationshipsDepthLevel = 0; 
creditCard = realm.copyFromRealm(creditCard, relationshipsDepthLevel); 
mApi.saveCreditCard(temporaryCard) 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(...); 

Przestarzałe ODPOWIEDŹ następująco:

I znaleziono obejście wymagającego 2 dodatkowe linie kodu i dodatkowy etap serializacji.

@Inject 
ObjectMapper mObjectMapper; // I use Dagger2 for DI 

.... 

CreditCard creditCard = realm.createObject(CreditCard.class); 
card.setWhateverField(...); 
... 
// I use Jackson's ObjectMapper to "copy" the original creditCard 
// to a new temporary instance that has not been tied to a Realm. 
String json = mObjectMapper.writeValueAsString(creditCard); 
PaymentCreditCardDataView temporaryCard = mObjectMapper 
        .reader(PaymentCreditCardDataView.class) 
        .readValue(json); 
mApi.saveCreditCard(temporaryCard) 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(...); 

Minusem jest to, że mam dodatkowy przedmiot i dodatkowy serializacji + deserialisation krok, na wątku UI. Powinno być ok, jeśli mam obiekty o rozsądnych rozmiarach.

+1

sprytne rozwiązanie – Loki