RxJava在toList()后subscribe()不执行的问题

12 篇文章 0 订阅
7 篇文章 0 订阅

今天在项目中遇到一个问题:需要遍历一个list在经过2次异步调用修改list中的一些值之后,刷新adapter,通知数据修改.略显复杂,一般的同步修改倒是没有什么了,但是需要进行2次异步调用修改,而且要跳过一些item,还要进行类型转换.最后还要根据异步调用返回的值进行排序,这个就略显复杂了.项目中引入了RxJava2,近几年的项目也一直都在用,今天面临的这种数据流的操作,最合适的也就是它了.

遍历

数据源就是一个list,很简单用fromIterable操作符就好了,这个操作符接收一个Iterable<? extends T> source,会依次发送里面的每一个item,发送完成后会调用onComplete()发送结束事件.

Observable.fromIterable(adatper!!.data)

跳过和转型

跳过的话可以调用skip(long count)操作符,它会跳过0..count个item,不像下游发送.转型的话直接使用map(Function<? super T, ? extends R> mapper)在里面把上游发送的被观察数据类型转为想要的类型就好了,会以新的类型继续向下游发送.

Observable.fromIterable(adatper!!.data).skip(3).map { it as Ques }

被观察者类型转换

今天的例子中,在开始的时候我接收到上游发送的数据后,需要进行异步调用,根据上游数据查询一个值,然后发送到下游,继续背观察.要实现这种功能的话要使用Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper)操作符,接收到上游数据后新建一个Observable返回给下游,异步回调后,调用这个Observable的emitter.onNext()把数据发送给下游.

Observable.create<Int> {
               RongIMClient.getInstance().getUnreadCount(Conversation.ConversationType.GROUP, bean.askCode, object : RongIMClient.ResultCallback<Int>() {
                    override fun onSuccess(p0: Int?) {
                        val old = bean.msgCount
                        if (old == p0 ?: 0) return
                        it.onNext(p0 ?: 0)
                        it.onComplete()
                    }

                    override fun onError(p0: RongIMClient.ErrorCode?) {
                        val old = bean.msgCount
                        if (old == 0) return
                        it.onNext(0)
                        it.onComplete()
                    }
                })
            }

合并2个Observable

上面的异步调用我进行了2次,获取到不同的值后,需要合并并发送到下游,下游接收到已经统一处理,notify adapter更新.实现这个功能可以使用zip()操作符,合并2个Observable并发送到下游,使用.zipWith()效果也是一样的.

Observable.zip(countOb, msgOb, object : BiFunction<Int, Triple<String, String,String>, Ques> {
                override fun apply(t1: Int, t2: Triple<String, String,String>): Ques {
                    bean.msgCount = t1
                    if (t2.first.isNotEmpty()) {
                        bean.content = t2.first
                    }
                    bean.questionTime = t2.second
                    bean.sortTime = t2.third
                    return bean
                }

            })

组合上游item为list

每个item都经过处理后会依次被下游的Observer接收到,但是我每次只接收一个插入到adapter然后notify,总是感觉不够优雅,在全部接收完之后再统一notify会不会更好了?这个时候就可以使用toList()操作符了,它会收集上游发送的所有item放到一个list中,直到上游调用onComplete()后将整个list发送到下游.而且还提供了一个toSortedList()的操作符可以对这个list进行排序,可以传入Comparator进行自定义排序,可谓非常的方便.

.toSortedList { o1, o2 ->
                o2.sortTime.compareTo(o1.sortTime)
            }

改进和踩坑

代码写到后面,发现不用把异步调用的结果单独进行发射,因为结果最后也要赋值给被观察item的成员变量,这种情况下使用别的操作符来代替flatMap行不行呢?或许是可以的,改天有应该试试,总之zip操作符在我的处理流中就暂时舍去了.把异步调用的结果直接赋值给上游发送的item再把这个item发射出去,(那用doOnNext()行不行呢?doOnNext()接收上游发送的item但是并不返回或者发送这个item,待测试),

我在写完上述代码后添加了toSortedList()操作符,这个时候意想不到的情况出现了,这个也是今天要说的重点:

后续的subscribe()没有被调用,toSortedList()自身也没有被调用,开始以为是线程切换的问题,删除线程切换后问题依旧,搜索后说是上游没有调用onComplete(),但是我的源头是使用的fromIterable()啊肯定是会调用onComplete()的,查看源码也证实了这一点,到这里就卡住了.

我没有想到的是源头虽然调用了onComplete(),但是中游的flatMap()并没有调用啊,开始我一厢情愿的以为fromIterable()onComplete()事件会跟着流一直传递,事实证明我想得太天真,对源码也没有深耕.想到这一点后在中游的flatMap()加入onComplete()的调用,问题就解决了.

最后的代码如下:

Observable.fromIterable(adatper!!.data)
						.skip(3)//跳过不需要的数据
            .map { it as Ques }//转型
            .flatMap { ques ->//进行异步调用
                Observable.create<Ques> {RongIMClient.getInstance().getUnreadCount(Conversation.ConversationType.GROUP, ques.askCode, object : RongIMClient.ResultCallback<Int>() {
                        override fun onSuccess(p0: Int?) {
                            ques.msgCount = p0 ?: 0
                            it.onNext(ques)//发射异步调用结果
                            it.onComplete()//别忘了这个哦
                        }

                        override fun onError(p0: RongIMClient.ErrorCode?) {
                            ques.msgCount = 0
                            it.onNext(ques)
                            it.onComplete()
                        }
                    })
                }
            }.flatMap { ques ->
                Observable.create<Ques> {RongIMClient.getInstance().getLatestMessages(Conversation.ConversationType.GROUP, ques.askCode, 1, object : RongIMClient.ResultCallback<List<Message>>() {
                        override fun onSuccess(p0: List<Message>?) {
                            if (p0?.isNotEmpty() == true) {
                                val message = p0[0]
                                val content = message.content
                                val isToday = TimeUtils.getTimeSpanByNow(message.receivedTime, TimeConstants.DAY) == 0L
                                val timeStr = if (isToday) {
                                    TimeUtils.millis2String(message.receivedTime, TimeUtils.FORMAT_HH_mm)
                                } else {
                                    TimeUtils.millis2String(message.receivedTime, TimeUtils.FORMAT_yyyy_MM_dd)
                                }
                                ques.questionTime = timeStr
                                ques.sortTime = TimeUtils.millis2String(message.receivedTime)
                                if (content is TextMessage) {
                                    ques.content = content.content
                                }
                                it.onNext(ques)
                            } else {
                                ques.sortTime = ques.questionTime
                                it.onNext(ques)
                            }
                            it.onComplete()
                        }

                        override fun onError(p0: RongIMClient.ErrorCode?) {
                            it.onNext(ques)
                            it.onComplete()
                        }

                    })
                }
            }.toSortedList { o1, o2 ->//排序并组合成list
                o2.sortTime.compareTo(o1.sortTime)
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { t ->
                newList.addAll(t)
                adatper?.setNewData(newList)
            }

RxJava博大精深,上手简单,要玩6还差得远,暂记于此,多用多想,希望早点玩6.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值