我是整个函数式编程和反应式概念的新手,并试图解决以下问题。
我有一个API-Client,我正在使用Retrofit。 还有一个本地数据库,它充当API响应的持久缓存。
我想要实现的是这样的事情:
我想出的是以下内容:
defaultIfEmpty
}
我遇到的问题是,如果数据库返回null,我的订阅回调中不会返回任何对象。
我已经尝试了 pwdStrength.SetPassword(text_passmysql.Text);
pwdStrength1.SetPassword(text_adminpass.Text);
switch (pwdStrength.GetPasswordStrength() || pwdStrength1.GetPasswordStrength())
{
case "Very Weak":
case "Weak":
// Show an error message to the user
MessageBox.Show("A password do MySQL é muito fraca, escolha um mais forte.\nApenas pode alterar a password MySQL para uma mais forte, caso contrário não será guardada.", "Configurações do Programa", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case "Good":
case "Strong":
case "Very Strong":
// Password deemed strong enough, allow user to be added to database etc
//do something
break;
}
- 方法但得出的结论是,这也无济于事,因为它期望一个对象而不是一个可观察对象。
任何想法,如何解决这个问题?
答案 0 :(得分:1)
您应该使用Flowables代替。无论如何, RxJava 2.x no longer accepts null values and will yield NullPointerException immediately or as a signal to downstream。如果你切换到Flowables,那么你可以使用像 .onErrorReturnItem(Collections.emptyList())这样的东西,它比它给你多少信息的空白要好。没有结果,而不是null可能意味着不同数量的东西。
答案 1 :(得分:0)
我对原始答案进行了一些重新评估,并得出结论,大多数现场检查网络响应/从网络获取数据的需求根本不需要。
首先,如果网络请求出现问题,则抛出异常,该异常将上升并由observable的onError-subscriber处理。
其次,还不需要检查请求是否成功,因为通过使用异常,只有在调用链中的下一步时才能成功。
而且第三,takeWhile
的使用使事情变得更加复杂,因为它实际上是必需的。
我决定使用一个简单的flatMap-Lambda来解决这个问题,它在内部使用了非常简单的if语句。因此,我认为代码更具可读性和可理解性。
您可以在下面找到我的问题的最终解决方案:
package com.appenetic.fame.model.repository.remote;
import android.support.annotation.NonNull;
import com.annimon.stream.Optional;
import com.appenetic.fame.api.service.LocationService;
import com.appenetic.fame.api.service.LocationServiceQueryBuilder;
import com.appenetic.fame.model.LocationCollection;
import com.appenetic.fame.model.repository.local.LocalLocationCollectionRepository;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import java.io.IOException;
import io.reactivex.Observable;
/**
* Created by shel on 18.01.18.
*/
public class LocationCollectionRepository {
private final static Integer fetchInterval = 30; //Minutes
private final LocationService locationService;
private final LocalLocationCollectionRepository localRepository;
public LocationCollectionRepository(@NonNull LocationService locationService, @NonNull LocalLocationCollectionRepository localRepository) {
this.locationService = locationService;
this.localRepository = localRepository;
}
public Observable<LocationCollection> getLocationCollection() throws IOException {
return localRepository.getLocationCollection()
.flatMap(locationCollectionOptional -> {
if (shouldFetch(locationCollectionOptional)) {
return persistLocationCollection(fetchLocationCollection().blockingFirst());
}
return Observable.just(locationCollectionOptional.get());
});
}
//================================================================================
// Private methods
//================================================================================
private Observable<LocationCollection> fetchLocationCollection() throws IOException {
return Observable.fromCallable(() -> {
LocationServiceQueryBuilder queryBuilder = LocationServiceQueryBuilder.query();
return queryBuilder.invoke(locationService).execute().body();
});
}
private Observable<LocationCollection> persistLocationCollection(@NonNull LocationCollection locationCollection) {
return localRepository.saveLocationCollection(locationCollection);
}
private boolean shouldFetch(@NonNull Optional<LocationCollection> locationCollection) {
if (locationCollection.isPresent()) {
Interval interval = new Interval(new DateTime(locationCollection.get().getTimestamp()), new DateTime());
return locationCollection.get().getHashValue() == null || interval.toDuration().getStandardMinutes() > fetchInterval;
} else {
return true;
}
}
}