在RxJava2中处理null

时间:2018-03-09 14:39:16

标签: rx-java2

我需要从本地或远程加载数据。如果获取了本地数据,则不会获取远程数据。

由于本地数据可以为空(即空),我必须处理RxJava2中的null情况,所以我在java-中Optional util的帮助下完成8。这是代码。

String data;

Observable<Optional<String>> loadCacheData() {
    return Observable.create(emitter -> {
        emitter.onNext(Optional.ofNullable(null));
        emitter.onComplete();
    });
}

Observable<Optional<String>> loadRemoteData() {
    Observable<Optional<String>> remoteObservable = Observable.create((ObservableOnSubscribe<Optional<String>>) emitter -> {
        Thread.sleep(2000);
        emitter.onNext(Optional.of("FromRemote"));
        emitter.onComplete();
    }).subscribeOn(Schedulers.io());

    remoteObservable.doOnNext(s -> data = s.get());

    return remoteObservable;
}

void fetchData() {
    Observable.concat(loadCacheData(), loadRemoteData())
            .filter(s -> s.isPresent())
            .firstElement()
            .subscribe(s -> System.out.println(s.get()));
}

我想知道在这种情况下是否还有其他方法可以处理null。

3 个答案:

答案 0 :(得分:2)

您无法将null发送至RxJava2不应发送,而是可以传递空数据列表。

switchIfEmpty()方法可以在两种情况下帮助您(网络和本地呼叫)。

答案 1 :(得分:1)

我在很多项目中都看到过返回静态&#39; DEFAULT&#39;给定类的对象。我不太了解这个解决方案,但它实际上是在RxJava中处理null的其他(并不是那么罕见)方法。

它看起来像这样:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    print(info)
    if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
        print(pickedImage)
        print(pickedImage.size)
    }


}

然后检查:

class Anything(...) {
   companion object {
       val DEFAULT = Anything(...)
   }
}

Observable.fromCallable { getAnythingObject() }
            .onErrorReturn { Anything.DEFAULT }

答案 2 :(得分:1)

您尝试做的似乎正是Maybe提供的内容:可以拥有或不拥有数据的来源。

以下是我看到这种方式的一个例子:

public class MaybeExample {

    private final Network network;

    private String cachedData;

    public MaybeExample(final MaybeNetwork network) {
        this.network = network;
    }

    // Just used for the test... you'll probably have something smarter
    public void setCachedData(final String data) {
        cachedData = data;
    }

    private Maybe<String> loadCacheData() {
        return cachedData != null ? Maybe.just(cachedData) : Maybe.empty();
    }

    private Single<String> loadRemoteData() {
        return network.getData();
    }

    public Single<String> fetchData() {
        return loadCacheData().switchIfEmpty(loadRemoteData());
    }
}

这将是一个测试,看看它在行动:

public class MaybeExampleTest {

    @Mock
    private Network network;

    private MaybeExample maybeExample;

    @Before
    public void createExample() {
        MockitoAnnotations.initMocks(this);
        maybeExample = new MaybeExample(network);
    }

    @Test
    public void nullCachedDataReturnsNetworkData() {
        maybeExample.setCachedData(null);
        final String networkValue = "FromNetwork";
        when(network.getData()).thenReturn(Single.just(networkValue));

        final TestObserver<String> observer = maybeExample.fetchData().test();

        observer.assertValue(networkValue);
    }

    @Test
    public void cachedDataIsReturnedWithoutCallingNetwork() {
        final String cachedValue = "FromCache";
        maybeExample.setCachedData(cachedValue);
        when(network.getData()).thenReturn(Single.error(new UnsupportedOperationException()));

        final TestObserver<String> observer = maybeExample.fetchData().test();

        observer.assertValue(cachedValue);
        observer.assertNoErrors();
    }
}