我正在尝试将我的对象从Retrofit直接保存到Realm,但总是得到错误:“Realm访问来自错误的线程”。
这是我的代码:
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);
}
});
}
}
答案 0 :(得分:1)
realm = Realm.getDefaultInstance();
将返回创建对象的线程的实例。但是Observable.map()
在observable发送消息的线程上被调用。
由于可观察性来自Retrofit,因此可以有两个选项:
Observable.subscribe
上执行。如果应用的选项与创建对象的选项不同,则将抛出“来自错误线程的域访问”错误。
答案 1 :(得分:1)
您应该在接收API结果的后台线程上打开Realm实例。
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查询Realm的UI线程实例。
答案 2 :(得分:0)
领域is thread confined,这意味着您需要确保在您获得引用的同一个线程上对Realm对象和realm
实例进行调用。您可能希望使用RxAndroid中的调度方法observeOn()
来确保在与realm::executeTransaction()
实例相同的线程上调用realm
。