首页 文章

在RxJava2中处理null

提问于
浏览
1

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

As local data can be empty (i.e. null) ,我必须处理RxJava2中的 null 情况,所以我在java-8中使用 Optional util帮助 . 这是代码 .

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 回答

  • 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();
        }
    }
    
  • 2

    您无法将 null 发送到 RxJava2you shouldn't do that ,而是可以传递数据的空列表 .

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

  • 1

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

    它看起来像这样:

    class Anything(...) {
       companion object {
           val DEFAULT = Anything(...)
       }
    }
    
    Observable.fromCallable { getAnythingObject() }
                .onErrorReturn { Anything.DEFAULT }
    

    然后检查:

    fun onReceived(anything: Anything) =
            when {
                anything === Anything.DEFAULT -> <TA DA!>
            }
    

相关问题