使用Retrofit和Realm在RxJava中纠正流程

Mic*_*hał 5 android realm rx-java retrofit retrolambda

我正在使用RxJava和Retrofit的组合实现网络API,我使用Realm作为我的数据库.我得到了相当多的工作,但我想知道它是否是正确的方法和事件的流程.所以,这是RetrofitApiManager.

public class RetrofitApiManager {

    private static final String BASE_URL = "***";

    private final ShopApi shopApi;

    public RetrofitApiManager(OkHttpClient okHttpClient) {

        // GSON INITIALIZATION

        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(BASE_URL)
                .build();

        shopApi = retrofit.create(ShopApi.class);
    }

    public Observable<RealmResults<Shop>> getShops() {
        return shopApi.getShops()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(response -> {
                    Realm realm = Realm.getDefaultInstance();
                    realm.executeTransaction(realm1 -> 
                            realm1.copyToRealmOrUpdate(response.shops));
                    realm.close();
                })
                .flatMap(response -> {
                    Realm realm = Realm.getDefaultInstance();
                    Observable<RealmResults<Shop>> results = realm.where(Shop.class)
                            .findAllAsync()
                            .asObservable()
                            .filter(RealmResults::isLoaded);
                    realm.close();
                    return results;
                });
    }
}
Run Code Online (Sandbox Code Playgroud)

这是呼吁RealmResults<Shop>进入一个Fragment.

realm.where(Shop.class)
        .findAllAsync()
        .asObservable()
        .filter(RealmResults::isLoaded)
        .first()
        .flatMap(shops -> 
                shops.isEmpty() ? retrofitApiManager.getShops() : Observable.just(shops))
        .subscribe(
                shops -> initRecyclerView(),
                throwable -> processError(throwable));
Run Code Online (Sandbox Code Playgroud)

这是我的问题:

  1. 它是链接事件的正确方法,如上例所示,还是应该以不同的方式管理它们?

  2. 可以RealmgetShops()方法中使用实例并关闭我或者将它作为参数传递然后以某种方式管理它会更好吗?虽然,这个想法似乎有点问题,线程和呼叫Realm.close()总是在正确的时间.

Chr*_*ior 10

1)我会尝试在后台线程上尽可能多地做,现在你在UI线程上做了很多工作.

2)

  public Observable<RealmResults<Shop>> getShops() {
        return shopApi.getShops()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(response -> {
                    try(Realm realm = Realm.getDefaultInstance()) {
                        realm.executeTransaction(realm1 -> 
                            realm1.insertOrUpdate(response.shops));
                    } // auto-close
                })
                .flatMap(response -> {
                    try(Realm realm = Realm.getDefaultInstance()) {
                        Observable<RealmResults<Shop>> results = realm.where(Shop.class)
                            .findAllAsync()
                            .asObservable()
                            .filter(RealmResults::isLoaded);
                    } // auto-close
                    return results;
                });
    }
Run Code Online (Sandbox Code Playgroud)

所有Realm数据都是延迟加载的,所以它只在Realm实例打开时才可用,因此在检索它之后关闭它很有可能无法正常工作.在你的情况下,虽然你是主线程上的平面映射,所以很可能已经有一个打开的实例.

如果您希望可以使用copyFromRealm()来获取可以跨线程移动的非托管数据,并且不再连接到Realm,但它们也将失去其实时更新功能并占用更多内存.

它可能会这样做:

  public Observable<RealmResults<Shop>> getShops() {
        return shopApi.getShops()
                .subscribeOn(Schedulers.io())
                .doOnNext(response -> {
                    try(Realm realm = Realm.getDefaultInstance()) {
                        realm.executeTransaction(realm1 -> 
                            realm1.copyToRealmOrUpdate(response.shops));
                    } // auto-close
                })
                .observeOn(AndroidSchedulers.mainThread())
                .flatMap(response -> {
                    Observable<RealmResults<Shop>> results = realm.where(Shop.class)
                            .findAllAsync()
                            .asObservable()
                            .filter(RealmResults::isLoaded);
                    return results;
                });
Run Code Online (Sandbox Code Playgroud)

或者,您可以将网络请求视为副作用,并且只是依赖于Realm在有更改时通知您(更好地接近IMO,因为您将网络与数据库访问分开,例如存储库模式的内容)

public Observable<RealmResults<Shop>> getShops() {
    // Realm will automatically notify this observable whenever data is saved from the network
    return realm.where(Shop.class).findAllAsync().asObservable()
            .filter(RealmResults::isLoaded)
            .doOnNext(results -> {
                if (results.size() == 0) {
                    loadShopsFromNetwork();
                }
            }); 
}

private void loadShopsFromNetwork() {
    shopApi.getShops()
            .subscribeOn(Schedulers.io())
            .subscribe(response -> {
                try(Realm realm = Realm.getDefaultInstance()) {
                    realm.executeTransaction(r -> r.insertOrUpdate(response.shops));
                } // auto-close
            });
}
Run Code Online (Sandbox Code Playgroud)