RxSwift网络琏式请求总结

img

RxSwift是在 Apple 推出 Swift 后, ReactiveX 推出 Reactive Extensions 系列一个实现库。下面介绍工作中使用RxSwift解决异步网络请求场景的实践。

img
img

业务场景为根据当前定位位置请求附近公交、地铁、水巴数据。根据右侧的筛选项筛选出不同的数据,进行请求。

创建数据事件源Observable

  • 请求地铁网络数据
func searchSubwayData(_ location: CLLocationCoordinate2D, _ isUserLocation: Bool = false) -> Observable<Bool> {
    return Observable<Bool>.create { [weak self] (observer) -> Disposable in
        let send = SubwaySendModel()
        send.latitude = location.latitude
        send.longitude = location.longitude
        send.range = 500
        SubwayNetwork.This.doTask(SubwayNetwork.CMD_getByCoord, data: send, controller: nil, success: {[weak self] (response: SubwayResponseModel?) in
            observer.onCompleted()
            guard let resp = response else {return}
            guard resp.line.count > 0 else {return}
            if isUserLocation == true {
                self?.subWayResponseModel = nil
                self?.subWayResponseModel = response
            }
            guard resp.station.count > 0 else {return}
            guard let stations: [SubwayStationModel] = (resp.station as NSArray).jsonArray() else {return}
            
            for model in stations {
                let annotation = RyHomeMAPointAnnotation(.subway)
                annotation.title = model.name
                annotation.coordinate = JZLocationConverter.wgs84(toGcj02: CLLocationCoordinate2D.init(latitude: CLLocationDegrees(model.latitude), longitude: CLLocationDegrees(model.longitude)))
                let nearStationModel = RyHomeNearStationModel()
                nearStationModel.name = model.name
                nearStationModel.desc = model.lines
                let nlocation = CLLocation.init(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude)
                nearStationModel.sid = "\(model.id)"
                nearStationModel.mtype = .subway
                if let userLocation = self?.mapView.userLocation.location {
                    nearStationModel.locationDistance = userLocation.distance(from: nlocation)
                }
                nearStationModel.location = nlocation
                annotation.mStationModel = nearStationModel
                self?.nearStationModelArr.append(nearStationModel)
                self?.subwayAnnotations.append(annotation)
            }
            self?.mapView.addAnnotations(self?.subwayAnnotations)
            
            }, error: { [weak self] (err, msg) in
                self?.subWayResponseModel = nil
                observer.onError(TestError.test)
            }, com: nil, showWait: false)
        
        return Disposables.create()
    }
}
  • 请求水巴网络数据
func searchBoatData(_ location: CLLocationCoordinate2D, _ isUserLocation: Bool = false) -> Observable<Bool> {
    return Observable<Bool>.create { [weak self] (observer) -> Disposable in
        let send = WaterBusSendModel()
        send.latitude = location.latitude
        send.longitude = location.longitude
        send.range = 500
        
        WaterBusNetWork.This.doArrayTask(WaterBusNetWork.CMD_getByCoord, data: send, controller: nil, success: { [weak self] (response: [ShuiBaStationModel]?) in
            observer.onCompleted()
            guard let stations = response else {return}
            guard stations.count > 0 else {return}
            if isUserLocation == true {
                self?.shuibaResponseArr = nil
                self?.shuibaResponseArr = stations
            }
            
            for model in stations {
                let annotation = RyHomeMAPointAnnotation(.boat)
                annotation.title = model.n
                annotation.coordinate = JZLocationConverter.wgs84(toGcj02: CLLocationCoordinate2D.init(latitude: CLLocationDegrees(model.la), longitude: CLLocationDegrees(model.lo)))
                let nearStationModel = RyHomeNearStationModel()
                nearStationModel.name = model.n
                nearStationModel.desc = "途径\(model.rcount ?? "0")条线路"
                let nlocation = CLLocation.init(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude)
                nearStationModel.sid = model.i
                nearStationModel.mtype = .boat
                if let userLocation = self?.mapView.userLocation.location {
                    nearStationModel.locationDistance = userLocation.distance(from: nlocation)
                }
                nearStationModel.location = nlocation
                annotation.mStationModel = nearStationModel
                self?.nearStationModelArr.append(nearStationModel)
                self?.boatAnnotations.append(annotation)
            }
            self?.mapView.addAnnotations(self?.boatAnnotations)
            
            }, error: { [weak self] (_, _) in
                self?.shuibaResponseArr = nil
                observer.onError(TestError.test)
            }, com: nil, showWait: false)
        
        return Disposables.create()
    }
}
  • 请求公交站网络数据
func searchBusStationData(_ location: CLLocationCoordinate2D) -> Observable<Bool> {
    return Observable<Bool>.create { [weak self] (observer) -> Disposable in
        let send = SendGetFullStationByCoord()
        send.latitude = location.latitude
        send.longitude = location.longitude
        send.range = 500
        send.withLCheck = true
        BusNetWork.This.doArrayTask(BusNetWork.CMD_getByCoord, data: send, controller: self, success: { (responseObj:[GetFullStationByCoord]?) in
            observer.onCompleted()
            guard let stations = responseObj else {return}
            guard stations.count > 0 else {return}
            
            for model in stations {
                let annotation = RyHomeMAPointAnnotation(.busStation)
                annotation.title = model.n
                annotation.coordinate = JZLocationConverter.wgs84(toGcj02: CLLocationCoordinate2D.init(latitude: CLLocationDegrees(model.la), longitude: CLLocationDegrees(model.lo)))
                let nearStationModel = RyHomeNearStationModel()
                nearStationModel.name = model.n
                nearStationModel.desc = "途径\(model.c)条线路"
                let nlocation = CLLocation.init(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude)
                nearStationModel.sid = model.i
                nearStationModel.mtype = .busStation
                nearStationModel.linec = Int(model.c)
                if let userLocation = self?.mapView.userLocation.location {
                    nearStationModel.locationDistance = userLocation.distance(from: nlocation)
                }
                nearStationModel.location = nlocation
                annotation.mStationModel = nearStationModel
                self?.nearStationModelArr.append(nearStationModel)
                self?.busStationAnnotations.append(annotation)
            }
            self?.mapView.addAnnotations(self?.busStationAnnotations)
            
        }, error: { (_, _) in
            observer.onError(TestError.test)
        }, com: nil, showWait: false)
        
        return Disposables.create()
    }
    
}

代码中Observable<Bool>.create { }是创建一个被观察者,observer.onCompleted()是网络数据请求回来,当前观察者发送完成信号,开始处理下一个事件,observer.onError(TestError.test)是网络请求失败,发送失败信号,使整个事件序列重新开始请求。

Observable就是可被观察的,是事件源,可以被订阅,上面创建了三个Observable,下面我们可以通过concat,把创建的三个事件联合起来一起被订阅。

联合订阅事件源

let disposeBag = DisposeBag()
func getData(_ isUserLocation: Bool = false) {
    ryHomeRightCategoryView.updateFilterIcon(filterType)
    
    guard let location = movedLocationCoordinate else {return}
    
    mapView.removeOverlays(mapView.overlays)
    addOverlay(location)
    mapView.removeAnnotations(subwayAnnotations)
    mapView.removeAnnotations(boatAnnotations)
    mapView.removeAnnotations(busStationAnnotations)
    subwayAnnotations.removeAll()
    boatAnnotations.removeAll()
    busStationAnnotations.removeAll()
    nearStationModelArr.removeAll()
    
    let wgsLocation = JZLocationConverter.gcj02(toWgs84: location)
    
    let symbol1 = searchSubwayData(wgsLocation)
    let symbol2 = searchBoatData(wgsLocation)
    let symbol3 = searchBusStationData(wgsLocation)
    
    var symbols: Observable<Observable<Bool>>? = nil
    if filterType == .subway {
        symbols = Observable.of(symbol1)
    }
    else if filterType == .boat {
        symbols = Observable.of(symbol2)
    }
    else if filterType == .bus {
        symbols = Observable.of(symbol3)
    }
    else if filterType == .all {
        symbols = Observable.of(symbol1, symbol2, symbol3)
    }
    symbols?.concat().retry(2).subscribe().addDisposableTo(disposeBag)
}

这个方法,通过concat把几个事件源联合起来进行订阅,就实现了多个网络的链式顺序请求。

  • 创建了地铁、水巴、公交站台三个被观察者的对象,这样方便后面进行筛选数据。
let symbol1 = searchSubwayData(wgsLocation)
let symbol2 = searchBoatData(wgsLocation)
let symbol3 = searchBusStationData(wgsLocation)
  • 创建事件源序列对象var symbols: Observable<Observable<Bool>>? = nil 根据当前的筛选类型filterType,给symbols进行赋值
var symbols: Observable<Observable<Bool>>? = nil
if filterType == .subway {
    symbols = Observable.of(symbol1)
}
else if filterType == .boat {
    symbols = Observable.of(symbol2)
}
else if filterType == .bus {
    symbols = Observable.of(symbol3)
}
else if filterType == .all {
    symbols = Observable.of(symbol1, symbol2, symbol3)
}
  • 联合订阅事件,把当前事件添加到释放池disposeBag,方便当前页面被释放后,被订阅的事件可以被释放。
symbols?.concat().retry(2).subscribe().addDisposableTo(disposeBag)

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容

  • 发现 关注 消息 RxSwift入坑解读-你所需要知道的各种概念 沸沸腾关注 2016.11.27 19:11*字...
    枫叶1234阅读 2,775评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 本篇文章介主要绍RxJava中操作符是以函数作为基本单位,与响应式编程作为结合使用的,对什么是操作、操作符都有哪些...
    嘎啦果安卓兽阅读 2,825评论 0 10
  • 亲爱的朋友, 祝好!现在窗外下着暴雨,电闪雷鸣,我躲在空调房里,给你写信。这场雨已经下了好几天了,不知为何,从昨...
    居无所处阅读 130评论 0 1
  • 死亡是一只静立的玻璃杯, 鲜血使它思想充盈, 注一剂冰冷,真理便在其中诞生。 一种欲望, 使它血脉狂贲,碎屑乘机浮...
    司贤阅读 381评论 0 1