RxJava onNext中的域事务冻结应用程序

问题描述 投票:2回答:1

建立

我使用Retrofit从REST API检索数据。我使用RxJava的Observable而不是Retrofit通常的反应。在onNext(Object obj)回调方法中,我告诉视图在地图上显示我通过API收到的每个项目的标记。另外,我想将每个条目保存到Realm数据库。

问题

保存到数据库工作。但是,它会阻止UI很长一段时间,有时会导致最多1000个跳帧。没有Realm部分,显示所有标记 - 尽管一次超过3000个(我出于性能和可用性原因将它们聚类)只需要几分之一秒。但是,随着它,应用程序似乎冻结了几秒钟。

保存到数据库可以工作,但Realm会填充所有条目。但它太慢了。

履行

(在将代码粘贴到此处之前,我进行了一些重命名和缩短代码,以显示我认为可能存在问题的部分。)

maps presenter.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();
                }
            });
        }
    }
}

realm controller.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;
    }

    ...
}

即使API调用后有几百个操作,如何提高插入/更新Realm条目的速度?我有什么东西可以俯瞰吗?

android performance realm rx-java
1个回答
2
投票

首先,真的很喜欢你构建问题的方式。

  1. 您的flatMap代码应该高于您的subscribeOn,以使其在observeOn中给出的Scheduler上运行。现在,代码正在MainThread上运行。
  2. 你正在MainThread上做Realm写操作,这很好但是你没有使用Realm给出的Aync方法,尝试在executeTransactionAsync块中执行write操作。
  3. 这个问题与您遇到的问题无关,但可以改进您在Presenter中处理订阅的方式。

示例示例如下所示,

public void fetchGitHubUsersFromRetrofit() {
  internetConnection.isInternetOn(context)
    .filter(connectionStatus -> connectionStatus)
    .switchMap(connectionStatus -> gitHubApiInterface.getGitHubUsersList())
    .subscribeOn(rxSchedulerConfiguration.getComputationThread())
    .observeOn(rxSchedulerConfiguration.getMainThread())
    .map(gitHubUserList -> {
      realm.executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(gitHubUserList));
    });
}

如果您正在寻找详细的代码参考,请查看此https://github.com/viraj49/Realm_android-injection-rx-test

© www.soinside.com 2019 - 2024. All rights reserved.