gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:01:57 26 4
gpt4 key购买 nike

我正在结合 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;
});
}
}

这是获取 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));

这是我的问题:

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

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

最佳答案

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;
});
}

所有 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;
});

或者,您可以将网络请求视为副作用,并仅依靠 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
});
}

关于android - 使用 Retrofit 和 Realm 在 RxJava 中纠正流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38052829/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com