Network API framework
Condy
Posted on February 3, 2022
RxNetworks
🧚. RxSwift + Moya + HandyJSON + Plugins.👒👒👒
English | 简体中文
This is a set of infrastructure based on RxSwift + Moya
MoyaNetwork
This module is based on the Moya encapsulated network API architecture.
- Mainly divided into 8 parts:
-
NetworkConfig: Set the configuration information at the beginning of the program.
- addDebugging:Whether to introduce the debug mode plugin by default.
- baseURL: Root path address to base URL.
- baseParameters: Default basic parameters, like: userID, token, etc.
- baseMethod: Default request method type.
- updateBaseParametersWithValue: Update default base parameter value.
-
RxMoyaProvider: Add responsiveness to network requests, returning
Single
sequence. -
NetworkUtil: Network related functions
- defaultPlugin: Add default plugin.
-
transformAPIObservableJSON: Transforms a
Observable
sequence JSON object. - handyConfigurationPlugin: Handles configuration plugins.
-
PluginSubType: Inherit and replace the Moya plug-in protocol to facilitate subsequent expansion.
- configuration: After setting the network configuration information, this method can be used in scenarios such as throwing data directly when the local cache exists without executing subsequent network requests.
- lastNever: When the last network response is returned, this method can be used in scenarios such as key failure to re-obtain the key and then automatically re-request the network.
-
NetworkAPI: Add protocol attributes and encapsulate basic network requests based on TargetType.
- ip: Root path address to base URL.
- parameters: Request parameters.
- plugins: Set network plugins.
- stubBehavior: Whether to take the test data.
- retry:Network request failure retries.
- request: Network request method and return a Single sequence object.
- NetworkAPI+Ext: Protocol default implementation scheme.
-
NetworkAPIOO: OOP converter, MVP to OOP, convenient for friends who are used to OC thinking
- cdy_ip: Root path address to base URL.
- cdy_path: Request path.
- cdy_parameters: Request parameters.
- cdy_plugins: Set network plugins.
- cdy_testJSON: Network testing json string.
- cdy_testTime: Network test data return time, the default is half a second.
- cdy_HTTPRequest: Network request method and return a Single sequence object.
-
NetworkX: extension function methods etc.
- toJSON: to JSON string.
- toDictionary: JSON string to dictionary.
- +=: Dictionary concatenation.
-
NetworkConfig: Set the configuration information at the beginning of the program.
🎷 - OO Example 1:
class OOViewModel: NSObject {
struct Input {
let retry: Int
}
struct Output {
let items: Observable<String>
}
func transform(input: Input) -> Output {
return Output(items: input.request())
}
}
extension OOViewModel.Input {
func request() -> Observable<String> {
var api = NetworkAPIOO.init()
api.cdy_ip = NetworkConfig.baseURL
api.cdy_path = "/ip"
api.cdy_method = APIMethod.get
api.cdy_plugins = [NetworkLoadingPlugin()]
api.cdy_retry = self.retry
return api.cdy_HTTPRequest()
.asObservable()
.compactMap{ (($0 as! NSDictionary)["origin"] as? String) }
.catchAndReturn("")
.observe(on: MainScheduler.instance)
}
}
🎷 - MVP Example 2:
enum LoadingAPI {
case test2(String)
}
extension LoadingAPI: NetworkAPI {
var ip: APIHost {
return NetworkConfig.baseURL
}
var path: String {
return "/post"
}
var parameters: APIParameters? {
switch self {
case .test2(let string): return ["key": string]
}
}
}
class LoadingViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<NSDictionary>()
/// Configure the loading animation plugin
let APIProvider: MoyaProvider<MultiTarget> = {
let configuration = URLSessionConfiguration.default
configuration.headers = .default
configuration.timeoutIntervalForRequest = 30
let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
let loading = NetworkLoadingPlugin.init()
return MoyaProvider<MultiTarget>(session: session, plugins: [loading])
}()
func loadData() {
APIProvider.rx.request(api: LoadingAPI.test2("666"))
.asObservable()
.subscribe { [weak self] (event) in
if let dict = event.element as? NSDictionary {
self?.data.accept(dict)
}
}.disposed(by: disposeBag)
}
}
🎷 - MVVM Example 3:
class CacheViewModel: NSObject {
struct Input {
let count: Int
}
struct Output {
let items: Observable<[CacheModel]>
}
func transform(input: Input) -> Output {
let items = request(input.count).asObservable()
return Output(items: items)
}
}
extension CacheViewModel {
func request(_ count: Int) -> Observable<[CacheModel]> {
CacheAPI.cache(count).request()
.mapHandyJSON(HandyDataModel<[CacheModel]>.self)
.compactMap { $0.data }
.observe(on: MainScheduler.instance) // the result is returned on the main thread
.catchAndReturn([]) // return null on error
}
}
🎷 - Chain Example 4:
class ChainViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<NSDictionary>()
func chainLoad() {
requestIP()
.flatMapLatest(requestData)
.subscribe(onNext: { [weak self] data in
self?.data.accept(data)
}, onError: {
print("Network Failed: \($0)")
}).disposed(by: disposeBag)
}
}
extension ChainViewModel {
func requestIP() -> Observable<String> {
return ChainAPI.test.request()
.asObservable()
.map { ($0 as! NSDictionary)["origin"] as! String }
.catchAndReturn("") // Exception thrown
}
func requestData(_ ip: String) -> Observable<NSDictionary> {
return ChainAPI.test2(ip).request()
.asObservable()
.map { ($0 as! NSDictionary) }
.catchAndReturn(["data": "nil"])
}
}
🎷 - Batch Example 5:
class BatchViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<NSDictionary>()
/// Configure loading animation plugin
let APIProvider: MoyaProvider<MultiTarget> = {
let configuration = URLSessionConfiguration.default
configuration.headers = .default
configuration.timeoutIntervalForRequest = 30
let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
let loading = NetworkLoadingPlugin.init()
return MoyaProvider<MultiTarget>(session: session, plugins: [loading])
}()
func batchLoad() {
Observable.zip(
APIProvider.rx.request(api: BatchAPI.test).asObservable(),
APIProvider.rx.request(api: BatchAPI.test2("666")).asObservable(),
APIProvider.rx.request(api: BatchAPI.test3).asObservable()
).subscribe(onNext: { [weak self] in
guard var data1 = $0 as? Dictionary<String, Any>,
let data2 = $1 as? Dictionary<String, Any>,
let data3 = $2 as? Dictionary<String, Any> else {
return
}
data1 += data2
data1 += data3
self?.data.accept(data1)
}, onError: {
print("Network Failed: \($0)")
}).disposed(by: disposeBag)
}
}
MoyaPlugins
This module is mainly based on moya package network related plugins
- At present, 6 plugins have been packaged for you to use:
🏠 - Simple to use, implement the protocol method in the API protocol, and then add the plugin to it:
var plugins: APIPlugins {
let cache = NetworkCachePlugin(cacheType: .networkElseCache)
let loading = NetworkLoadingPlugin.init(delay: 0.5)
let warning = NetworkWarningPlugin.init()
warning.changeHud = { (hud) in
hud.detailsLabel.textColor = UIColor.yellow
}
return [loading, cache, warning]
}
HandyJSON
This module is based on HandyJSON
package network data parsing
- Roughly divided into the following 3 parts:
- HandyDataModel: Network outer data model
- HandyJSONError: Parse error related
-
RxHandyJSON: HandyJSON data parsing, currently provides two parsing solutions
-
Option 1: Combine
HandyDataModel
model to parse out data. -
Option 2: Parse the data of the specified key according to
keyPath
, the precondition is that the json data source must be in the form of a dictionary.
-
Option 1: Combine
🎷 - Example of use in conjunction with the network part:
func request(_ count: Int) -> Driver<[CacheModel]> {
CacheAPI.cache(count).request()
.asObservable()
.mapHandyJSON(HandyDataModel<[CacheModel]>.self)
.compactMap { $0.data }
.observe(on: MainScheduler.instance)
.delay(.seconds(1), scheduler: MainScheduler.instance)
.asDriver(onErrorJustReturn: [])
}
CocoaPods Install
Ex: Import Network Architecture API
- pod 'RxNetworks/MoyaNetwork'
Ex: Import Model Anslysis
- pod 'RxNetworks/HandyJSON'
Ex: Import loading animation plugin
- pod 'RxNetworks/MoyaPlugins/Loading'
Remarks
The general process is almost like this, the Demo is also written in great detail, you can check it out for yourself.🎷
Tip: If you find it helpful, please help me with a star. If you have any questions or needs, you can also issue.
Thanks.🎇
About the author
- 🎷 E-mail address: yangkj310@gmail.com 🎷
- 🎸 GitHub address: yangKJ 🎸
Posted on February 3, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024