Setup
I retrieve data from a REST API using Retrofit. Instead of Retrofit’s usual response, I use RxJava’s Observable. In the onNext(Object obj)
callback method I tell the view to show markers on a map for each item I receive over the API. Additionally, I want to save each entry to a Realm database.
Problem
Saving to the database works. However, it blocks the UI for quite a while, sometimes leading to up to 1000 skipped frames. Without the Realm part, showing all the markers—although over 3000 at a time (I cluster them for performance and usability reasons) takes only fractions of a second. With it, though, the app seems to freeze for seconds.
Saving to the database works, though—the Realm gets populated with all entries. But it’s way too slow.
Implementation
(I did some renaming and shortened the code before pasting it here to just show what I think might be the problematic part.)
MapsPresenter.java
class MapsPresenter implements Presenter<MapsView> {
private MapsView mapsView;
private Subscription subscription;
private MyApiClient apiClient;
private Realm realm;
MapsPresenter() {
apiClient = MyApp.getMyApiClient();
realm = RealmController.with(MyApp.getInstance()).getRealm();
}
void loadRetailers(...) {
if (subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
mapsView.showProgressIndicator();
subscription = apiClient.retailers()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.flatMap(new Func1<Retailers, Observable<Retailer>>() {
@Override
public Observable<Dealer> call(Retailers retailers) {
return Observable.from(retailers.retailerList);
}
})
.subscribe(new Subscriber<Dealer>() {
@Override
public void onCompleted() {
...
}
@Override
public void onError(Throwable e) {
...
}
@Override
public void onNext(Retailer retailer) {
realm.beginTransaction();
realm.insertOrUpdate(retailer);
realm.commitTransaction();
}
});
}
}
}
RealmController.java
public class RealmController {
private static RealmController instance;
private final Realm realm;
public RealmController(Application application) {
realm = Realm.getDefaultInstance();
}
public static RealmController with(Application application) {
if (instance == null) {
instance = new RealmController(application);
}
return instance;
}
public static RealmController getInstance() {
return instance;
}
public Realm getRealm() {
return realm;
}
...
}
Question
How can I improve the speed of inserting/updating the Realm entries, even if there are a couple hundred operations following an API call? Is there something I’m overlooking?