改造 POST 领域对象

RETROFIT POST Realm object

我有以下改造API:

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

CreditCardRealmObject.

当我尝试使用我的 API 方法时:

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

我收到以下错误:

> 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.access0(RestAdapter.java:220)
System.err﹕ at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:265)
System.err﹕ at retrofit.RxSupport.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.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.

我假设 RETROFIT 正在 io() 调度程序上对 JSON 进行序列化,因此出现错误。

有没有人对我如何克服 Realm 的线程问题有任何建议?

更新

Realm 添加了对使用 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(...);

弃用的答案如下:

我找到了一个解决方法,它需要 2 行额外的代码和一个额外的序列化步骤。

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

缺点是我在 UI 线程上有一个额外的对象和一个额外的序列化+反序列化步骤。如果我有合适大小的物体应该没问题。