RX操作符之辅助操作符三(using、getIterator、toFuture、toIterator、toMap、toMultiMap、nest)

本文解析了RxJava中的关键操作符,包括using、first、firstOrDefault等,并介绍了如何使用这些操作符处理数据流,还详细说明了toFuture、toIterator等阻塞式操作符的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、using

创建一个只在Observable生命周期存在的资源

 //一个用户创建一次性资源的工厂函数
        Func0<Integer> resourceFactory = new Func0<Integer>() {

            @Override
            public Integer call() {
                return 1;
            }
        };

        //一个用于创建Observable的工厂函数
        Func1<Integer, Observable<String>> observableFactory = new Func1<Integer, Observable<String>>() {
            @Override
            public Observable<String> call(Integer integer) {
                return Observable.just(integer+"。。。。。。创建observable的工厂函数");
            }
        };

        //一个用于释放资源的函数
        Action1<Integer> disposeAction = new Action1<Integer>(){

            @Override
            public void call(Integer integer) {
                Log.e(TAG,"释放资源的函数。。。。。。。。。"+integer);
            }
        };

        Subscriber<String> subscriber = new Subscriber<String>() {

            @Override
            public void onNext(String v) {
                Log.e(TAG,"onNext................."+v);
            }

            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted.................");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError.....................");
            }
        };

        Observable.using(resourceFactory,observableFactory,disposeAction).subscribe(subscriber);


运行结果:



二、first

只发射第一项(或者满足某个条件的第一项)数据。如果你只对Observable发射的第一项数据,或者满足某个条件的第一项数据感兴趣,你可以使用First操作符。在某些实现中,First没有实现为一个返回Observable的过滤操作符,而是实现为一个在当时就发射原始Observable指定数据项的阻塞函数。在这些实现中,如果你想要的是一个过滤操作符,最好使用Take(1)ElementAt(0)

在一些实现中还有一个Single操作符。它的行为与First类似,但为了确保只发射单个值,它会等待原始Observable终止(否则,不是发射那个值,而是以一个错误通知终止)。你可以使用它从原始Observable获取第一项数据,而且也确保只发射一项数据。

在RxJava中,这个操作符被实现为firstfirstOrDefaulttakeFirst可能容易混淆,BlockingObservable也有名叫firstfirstOrDefault的操作符,它们会阻塞并返回值,不是立即返回一个Observable。


三、firstOrDefault

firstOrDefaultfirst类似,但是在Observagle没有发射任何数据时发射一个你在参数中指定的默认值。


四、single

single操作符也与first类似,但是如果原始Observable在完成之前不是正好发射一次数据,它会抛出一个NoSuchElementException

五、singleOrDefualt

firstOrDefault(T, Func1)类似,如果没有数据满足条件,返回默认值;如果有多个数据满足条件,以错误通知终止。

六、getIterator

getIterator操作符只能用于BlockingObservable的子类,要使用它,你首先必须把原始的Observable转换为一个BlockingObservable。可以使用这两个操作符:BlockingObservable.fromthe Observable.toBlocking将observable转成数据结果iterator类型,然后可以按iterator来获取数据。是阻塞式的,当有observable发出时才会输出数据。

每隔1s打印一个数据

 BlockingObservable<Long> blockingObservable = BlockingObservable.from(Observable.interval(1,TimeUnit.SECONDS).take(5));
        Iterator<Long> iterator = blockingObservable.getIterator();

        while (iterator.hasNext()){
            Log.e(TAG,"发出的数据是..............." + iterator.next());
        }

运行结果:



七、toFuture

toFuture操作符也是只能用于BlockingObservable。这个操作符将Observable转换为一个返回单个数据项的Future,如果原始Observable发射多个数据项,Future会收到一个IllegalArgumentException;如果原始Observable没有发射任何数据,Future会收到一个NoSuchElementException如果你想将发射多个数据项的Observable转换为Future,可以这样用:myObservable.toList().toBlocking().toFuture()

发射了多个数据,产生了异常

1.

 BlockingObservable<Long> blockingObservable = BlockingObservable.from(Observable.interval(1,TimeUnit.SECONDS).take(5));

        Future<Long> future = blockingObservable.toFuture();
        long l = -1;
        try {
            l = future.get();
        }catch (Exception e){

        }
        Log.e(TAG,"应该获取到的数据是....................."+l);


运行结果:


2.发送Observable集合,这个过程是阻塞的,当5s后才输出数据结果

 Future<List<Long>> futureList = Observable.interval(1, TimeUnit.SECONDS).take(5).toList().toBlocking().toFuture();

        List<Long> list= null;
        try {
            list = futureList.get();
            for(long l : list){
                Log.e(TAG,"取到的数据是....................."+l);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
运行结果:



八、toIterator

将observable转成数据类型iterable,阻塞式。toFuture操作符也是只能用于BlockingObservable。这个操作符将Observable转换为一个Iterable,你可以通过它迭代原始Observable发射的数据集。

Iterable<List<Long>> iterableList = Observable.interval(1, TimeUnit.SECONDS).take(5).toList().toBlocking().toIterable();

        Iterator<List<Long>> iteratorLists = null;
        List<Long> list = null;
        try {
            iteratorLists = iterableList.iterator();
            while (iteratorLists.hasNext()) {
                list = iteratorLists.next();
            }
            for(long l : list){
                Log.e(TAG,"取到的数据是....................."+l);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


九、toList

将Observable转成数据类型list,阻塞式。通常,发射多项数据的Observable会为每一项数据调用onNext方法。你可以用toList操作符改变这个行为,让Observable将多项数据组合成一个List,然后调用一次onNext方法传递整个列表。

如果原始Observable没有发射任何数据就调用了onCompletedtoList返回的Observable会在调用onCompleted之前发射一个空列表。如果原始Observable调用了onErrortoList返回的Observable会立即调用它的观察者的onError方法。


十、toMap

将Observable转成数据类型map,阻塞式。toMap收集原始Observable发射的所有数据项到一个Map(默认是HashMap)然后发射这个Map。你可以提供一个用于生成Map的Key的函数,还可以提供一个函数转换数据项到Map存储的值(默认数据项本身就是值)。

 Observable<Map<String, Long>> observable = Observable.interval(1, TimeUnit.SECONDS).take(5).toMap(new Func1<Long, String>() {
            @Override
            public String call(Long aLong) {
                return aLong + "";
            }
        });

        Subscriber<Map<String, Long>> subscriber = new Subscriber<Map<String, Long>>() {

            @Override
            public void onNext(Map<String, Long> map) {
                Set<Map.Entry<String, Long>> set =  map.entrySet();
                for(Map.Entry entry:set) {
                    Log.e(TAG, "onNext.................key:" + entry.getKey()+"...............value:"+entry.getValue());
                }
            }

            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted.................");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError.....................");
            }
        };


        observable.subscribe(subscriber);

运行结果:


十一、toMultiMap

toMultiMap类似于toMap,不同的是,它生成的这个Map同时还是一个ArrayList(默认是这样,你可以传递一个可选的工厂方法修改这个行为)。toMultiMap默认不在任何特定的调度器上执行。


 Observable<Map<String, Collection<Long>>> observable = Observable.interval(1, TimeUnit.SECONDS).take(5).toMultimap(new Func1<Long, String>() {
            @Override
            public String call(Long aLong) {
                return "testMultiMap" + aLong;
            }
        });

        Subscriber<Map<String, Collection<Long>>> subscriber = new Subscriber<Map<String, Collection<Long>>>() {

            @Override
            public void onNext(Map<String, Collection<Long>>map) {
                Set<Map.Entry<String, Collection<Long>>> set =  map.entrySet();
                for(Map.Entry entry:set) {
                    Log.e(TAG, "onNext.................key:" + entry.getKey()+"...............value:"+entry.getValue());
                }
            }

            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted.................");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError.....................");
            }
        };


        observable.subscribe(subscriber);
运行结果:



十二、toSortedList

oSortedList类似于toList,不同的是,它会对产生的列表排序,默认是自然升序,如果发射的数据项没有实现Comparable接口,会抛出一个异常。然而,你也可以传递一个函数作为用于比较两个数据项,这是toSortedList不会使用Comparable接口。

十三、nest

nest操作符有一个特殊的用途:将一个Observable转换为一个发射这个Observable的Observable。

 Observable<String> observable = Observable.just("nest1","nest2","nest3","nest4","nest5");
        final Subscriber<String> subscriber1 = new Subscriber<String>() {

            @Override
            public void onNext(String v) {
                Log.e(TAG, "onNext<String>................." + v);
            }

            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted.................");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError.....................");
            }
        };

        Subscriber<Observable<String>> subscriber = new Subscriber<Observable<String>>() {

            @Override
            public void onNext(Observable<String> v) {
                Log.e(TAG, "onNextObservable<String>................." + v.subscribe(subscriber1));
            }

            @Override
            public void onCompleted() {
                Log.e(TAG, "onCompleted.................");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError.....................");
            }
        };

        Observable<Observable<String>> observable1  = observable.nest();
        observable1.subscribe(subscriber);

运行结果:


<think>好的,用户想了解在React项目中使用postcss-pxtorem时遇到的问题及解决方案。我需要结合提供的引用内容来整理答案。首先,引用3提到了React中使用postcss-pxtorem的基本配置步骤,比如安装、webpack配置和参数设置。引用2和引用4提到了一些常见问题,比如lib-flexible在iPad上的兼容性问题,以及行内样式无法转换的问题。另外,引用1指出vue版本升级导致的问题,虽然用户问的是React,但可能需要注意类似版本兼容性问题。 首先,应该列举常见问题。根据引用2,lib-flexible在iPad上的兼容性问题,解决方法可能是改用vw/vh方案。然后,引用4提到行内样式的px不会被转换,需要手动处理。引用3中的配置参数如rootValue设置不正确可能导致计算错误,这也是一个常见问题。还有,postcss-pxtorem在React中的配置可能需要检查Webpack或Vite的配置是否正确,特别是在React 18或更新版本中是否存在兼容性问题,类似于引用1中的Vue版本问题。 解决方案部分,针对每个问题给出解决方法。例如,iPad兼容性问题可以改用viewport方案,行内样式需要开发者自己转换,配置参数需要根据设计稿调整rootValue,版本升级导致的插件问题可能需要降级或寻找替代插件。此外,可能还要提到排除第方库的情况,如引用3中的exclude配置,避免转换UI框架的样式。 需要确保回答结构清晰,分点列出问题和对应的解决措施,并引用对应的参考文献。同时注意使用中文,正确应用LaTeX格式,但根据用户的问题内容,可能数学公式较少,所以重点在代码块和引用标注。最后生成相关问题,比如如何配置rootValue,如何处理第方库样式等。</think>### React项目中postcss-pxtorem常见问题与解决方案 #### 1. **iPad设备兼容性问题** - **问题描述**:使用`lib-flexible`实现弹性布局时,可能出现iPad或iPad Pro显示异常(如内容缩放比例错误)[^2]。 - **解决方案**: 1. 改用`viewport`单位(vw/vh)替代`rem`方案; 2. 结合`postcss-px-to-viewport`插件直接转换px为视口单位[^4]。 #### 2. **行内样式无法转换** - **问题描述**:`postcss-pxtorem`只能转换CSS文件中的`px`,无法处理行内样式(如JSX中的`style={{ width: "10px" }}`)[^4]。 - **解决方案**: 1. 手动将行内样式的`px`转换为`rem`; 2. 使用CSS Modules或外部样式表替代行内样式。 #### 3. **rootValue配置错误** - **问题描述**:若`rootValue`值与设计稿基准值不匹配(如设计稿为750px宽度,但`rootValue`设为固定值19.2),会导致`rem`计算错误[^3]。 - **解决方案**: 1. 动态计算`rootValue`,例如: ```javascript rootValue: (module) => (module.file.includes("vant") ? 37.5 : 75) // 区分UI库和业务代码 ``` 2. 根据设计稿宽度按比例设置,如设计稿750px时,`rootValue = 75`(即1rem = 75px)。 #### 4. **第方UI框架样式失效** - **问题描述**:若未排除`node_modules`中的UI库(如Ant Design、Vant),可能导致组件样式异常。 - **解决方案**: 在配置中添加`exclude`正则表达式: ```javascript exclude: /(node_module)/ // 排除第方库目录 ``` #### 5. **版本兼容性问题** - **问题描述**:React 18+或工具链升级后,可能因插件版本不兼容导致报错(如`node.getIterator is not a function`)[^2]。 - **解决方案**: 1. 降级`postcss-pxtorem`至兼容版本; 2. 使用`postcss-px2rem`或`postcss-px-to-viewport`替代。 --- ### 配置示例(Webpack) ```javascript // webpack.config.js { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ require('postcss-pxtorem')({ rootValue: 75, propList: ['*'], exclude: /node_modules/, minPixelValue: 2 }) ] } } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值