iOS 使用Moya網(wǎng)絡(luò)請(qǐng)求

Moya最新版本11.0.2

由于前段時(shí)間寫(xiě)了這篇文章雏婶,最新Moya已更新最新版本过椎,故此也更新了下用法,本人已使用荸频,故特意奉上最新的使用demo供參考菱肖。
Moya11.0.2Demo

Moya簡(jiǎn)介

Moya 是你的 app 中缺失的網(wǎng)絡(luò)層。不用再去想在哪兒(或者如何)安放網(wǎng)絡(luò)請(qǐng)求旭从,Moya 替你管理稳强。

Moya有幾個(gè)比較好的特性:

  • 編譯時(shí)檢查正確的API端點(diǎn)訪問(wèn).

  • 使你定義不同端點(diǎn)枚舉值對(duì)應(yīng)相應(yīng)的用途更加明晰.

  • 提高測(cè)試地位從而使單元測(cè)試更加容易.

Swift我們用Alamofire來(lái)做網(wǎng)絡(luò)庫(kù).而Moya在Alamofire的基礎(chǔ)上又封裝了一層,如下流程圖說(shuō)明Moya的簡(jiǎn)單工作流程圖:

簡(jiǎn)單流程圖

** Moya**的官方下載地址點(diǎn)我強(qiáng)大的Moya,有具體的使用方法在demo里面有說(shuō)明。

本文主要介紹一下Moya的用法

  • 設(shè)置請(qǐng)求頭部信息
  • 設(shè)置超時(shí)時(shí)間
  • 自定義插件
  • 自簽名證書(shū)

注意:以下所出現(xiàn)的NetAPIManager跟官網(wǎng)上demo的** GitHub**是一樣類型的文件和悦,都是這個(gè)enum實(shí)現(xiàn)一個(gè)協(xié)議TargetType退疫,點(diǎn)進(jìn)去可以看到TargetType定義了我們發(fā)送一個(gè)網(wǎng)絡(luò)請(qǐng)求所需要的東西,什么baseURL鸽素,parameter褒繁,method等一些計(jì)算性屬性,我們要做的就是去實(shí)現(xiàn)這些東西馍忽,當(dāng)然有帶默認(rèn)值的我們可以不去實(shí)現(xiàn)棒坏,但是設(shè)置頭部信息跟超時(shí)時(shí)間就要修改這些系統(tǒng)默認(rèn)設(shè)置了燕差。

為了看得更加清楚,貼上NetAPIManager文件的內(nèi)容

//
//  NetAPIManager.swift
//  NN110
//
//  Created by 陳亦海 on 2017/5/12.
//  Copyright ? 2017年 陳亦海. All rights reserved.
//

import Foundation
import Moya


enum NetAPIManager {
    case Show
    case upload(bodyData: Data)
    case download
    case request(isTouch: Bool, body: Dictionary<String, Any>? ,isShow: Bool)
}


extension NetAPIManager: TargetType {
    var baseURL: URL {//服務(wù)器地址
        
        switch self {
        case .request( _, _, _):
            return URL(string: "https://www.pmphmall.com")!
        default:
            return URL(string: "https://httpbin.org")!
        }
        
        
    }
    
    var path: String {//具體某個(gè)方法的路徑
        switch self {
        case .Show:
            return ""
        case .upload(_):
            return ""
        case .request(_, _, _):
            return "/app/json.do"
        case .download:
            return ""
        }
    }
    
    var method: Moya.Method {//請(qǐng)求的方法 get或者post之類的
        switch self {
        case .Show:
            return .get
        case .request(_, _, _):
            return .post
        default:
            return .post
        }
    }
    
    var parameters: [String: Any]? {//請(qǐng)求的get post給服務(wù)器的參數(shù)
        switch self {
        case .Show:
            return nil
        case .request(_, _, _):
            return ["msg":"H4sIAAAAAAAAA11SSZJFIQi7EqPAEgTvf6TP62W7sMoSQhKSWDrs6ZUKVWogLwYV7RjHFBZJlNlzloN6LVqID4a+puxqRdUKVNLwE1TRcZIC/fjF2rPotuXmb84r1gMXbiASZIZbhQdKEewJlz41znDkujCHuQU3dU7G4/PmVRnwArMLXukBv0J23XVahNO3VX35wlgce6TLUzzgPQJFuHngAczl6VhaNXpmRLxJBlMml6gdLWiXxTdO7I+iEyC7XuTirCQXOk4dotgArgkH/InxVjfNTnE/uY46++hyAiLFuFL4cv1Z8WH5DgB2GnvFXMh5gm53Tr13vqqrEYtcdXfkNsMwKB+9sAQ77grNJmquFWOhfXA/DELlMB0KKFtHOc/ronj1ml+Z7qas82L3VWiCVQ+HEitjTVzoFw8RisFN/jJxBY4awvq427McXqnyrfCsl7oeEU6wYgW9yJtj1lOkx0ELL5Fw4z071NaVzRA9ebxWXkFyothgbB445cpRmTC+//F73r1kOyQ3lTpec12XNDR00nnq5/YmJItW3+w1z27lSOLqgVctrxG4xdL9WVPdkH1tkiZ/pUKBGhADAAA="]
        default:
            return nil
        
        }
    }
    
    var sampleData: Data { //編碼轉(zhuǎn)義
       return "{}".data(using: String.Encoding.utf8)!
    }
    
    var task: Task { //一個(gè)請(qǐng)求任務(wù)事件
        
        switch self {

        
        case let .upload(data):
        return .upload(.multipart([MultipartFormData(provider: .data(data), name: "file", fileName: "gif.gif", mimeType: "image/gif")]))
            
        default:
            return .request

       }

     }
    
    var parameterEncoding: ParameterEncoding {//編碼的格式
        switch self {
        case .request(_, _, _):
            return URLEncoding.default
        default:
            return URLEncoding.default
        }
        
    }
    //以下兩個(gè)參數(shù)是我自己寫(xiě)俊抵,用來(lái)控制網(wǎng)絡(luò)加載的時(shí)候是否允許操作谁不,跟是否要顯示加載提示坐梯,這兩個(gè)參數(shù)在自定義插件的時(shí)候會(huì)用到
    var touch: Bool { //是否可以操作
        
        switch self {
        case .request(let isTouch, _, _):
            return isTouch
        default:
            return false
        }
        
    }
    
    var show: Bool { //是否顯示轉(zhuǎn)圈提示
        
        switch self {
        case .request( _, _,let isShow):
            return isShow
        default:
            return false
        }
        
    }
    
    
}

如何設(shè)置Moya請(qǐng)求頭部信息

頭部信息的設(shè)置在開(kāi)發(fā)過(guò)程中很重要徽诲,如服務(wù)器生成的token,用戶唯一標(biāo)識(shí)等
我們直接上代碼吵血,不說(shuō)那么多理論的東西谎替,哈哈

// MARK: - 設(shè)置請(qǐng)求頭部信息
let myEndpointClosure = { (target: NetAPIManager) -> Endpoint<NetAPIManager> in
    
    
    let url = target.baseURL.appendingPathComponent(target.path).absoluteString
    let endpoint = Endpoint<NetAPIManager>(
        url: url,
        sampleResponseClosure: { .networkResponse(200, target.sampleData) },
        method: target.method,
        parameters: target.parameters,
        parameterEncoding: target.parameterEncoding
    )

    //在這里設(shè)置你的HTTP頭部信息
    return endpoint.adding(newHTTPHeaderFields: [
        "Content-Type" : "application/x-www-form-urlencoded",
        "ECP-COOKIE" : ""
        ])
    
}

如何設(shè)置請(qǐng)求超時(shí)時(shí)間

// MARK: - 設(shè)置請(qǐng)求超時(shí)時(shí)間
let requestClosure = { (endpoint: Endpoint<NetAPIManager>, done: @escaping MoyaProvider<NetAPIManager>.RequestResultClosure) in
    
    guard var request = endpoint.urlRequest else { return }
    
    request.timeoutInterval = 30    //設(shè)置請(qǐng)求超時(shí)時(shí)間
    done(.success(request))
}

自定義插件

自定義插件必須PluginType協(xié)議的兩個(gè)方法willSend與didReceive

//
//  MyNetworkActivityPlugin.swift
//  NN110
//
//  Created by 陳亦海 on 2017/5/10.
//  Copyright ? 2017年 CocoaPods. All rights reserved.
//

import Foundation
import Result
import Moya


/// Network activity change notification type.
public enum MyNetworkActivityChangeType {
    case began, ended
}

/// Notify a request's network activity changes (request begins or ends).
public final class MyNetworkActivityPlugin: PluginType {
    
    
    
    public typealias MyNetworkActivityClosure = (_ change: MyNetworkActivityChangeType, _ target: TargetType) -> Void
    let myNetworkActivityClosure: MyNetworkActivityClosure
    
    public init(newNetworkActivityClosure: @escaping MyNetworkActivityClosure) {
        self.myNetworkActivityClosure = newNetworkActivityClosure
    }
    
    // MARK: Plugin
    
    /// Called by the provider as soon as the request is about to start
    public func willSend(_ request: RequestType, target: TargetType) {
        myNetworkActivityClosure(.began,target)
    }
    
    /// Called by the provider as soon as a response arrives, even if the request is cancelled.
    public func didReceive(_ result: Result<Moya.Response, MoyaError>, target: TargetType) {
        myNetworkActivityClosure(.ended,target)
    }
}

使用自定義插件方法

// MARK: - 自定義的網(wǎng)絡(luò)提示請(qǐng)求插件
let myNetworkPlugin = MyNetworkActivityPlugin { (state,target) in
    if state == .began {
        //        SwiftSpinner.show("Connecting...")
        
        let api = target as! NetAPIManager
        if api.show {
            print("我可以在這里寫(xiě)加載提示")
        }
        
        if !api.touch {
            print("我可以在這里寫(xiě)禁止用戶操作,等待請(qǐng)求結(jié)束")
        }

        print("我開(kāi)始請(qǐng)求\(api.touch)")
        
        UIApplication.shared.isNetworkActivityIndicatorVisible = true
    } else {
        //        SwiftSpinner.show("request finish...")
        //        SwiftSpinner.hide()
        print("我結(jié)束請(qǐng)求")
        UIApplication.shared.isNetworkActivityIndicatorVisible = false
        
    }
}

自簽名證書(shū)

在16年的WWDC中蹋辅,Apple已表示將從2017年1月1日起钱贯,所有新提交的App必須強(qiáng)制性應(yīng)用HTTPS協(xié)議來(lái)進(jìn)行網(wǎng)絡(luò)請(qǐng)求。默認(rèn)情況下非HTTPS的網(wǎng)絡(luò)訪問(wèn)是禁止的并且不能再通過(guò)簡(jiǎn)單粗暴的向Info.plist中添加NSAllowsArbitraryLoads
設(shè)置繞過(guò)ATS(App Transport Security)的限制(否則須在應(yīng)用審核時(shí)進(jìn)行說(shuō)明并很可能會(huì)被拒)侦另。所以還未進(jìn)行相應(yīng)配置的公司需要盡快將升級(jí)為HTTPS的事項(xiàng)提上進(jìn)程了秩命。本文將簡(jiǎn)述HTTPS及配置數(shù)字證書(shū)的原理并以配置實(shí)例和出現(xiàn)的問(wèn)題進(jìn)行說(shuō)明,希望能對(duì)你提供幫助褒傅。(比心~)


HTTPS:
簡(jiǎn)單來(lái)說(shuō)弃锐,HTTPS就是HTTP協(xié)議上再加一層加密處理的SSL協(xié)議,即HTTP安全版。相比HTTP殿托,HTTPS可以保證內(nèi)容在傳輸過(guò)程中不會(huì)被第三方查看霹菊、及時(shí)發(fā)現(xiàn)被第三方篡改的傳輸內(nèi)容、防止身份冒充支竹,從而更有效的保證網(wǎng)絡(luò)數(shù)據(jù)的安全旋廷。
HTTPS客戶端與服務(wù)器交互過(guò)程:
1、 客戶端第一次請(qǐng)求時(shí)礼搁,服務(wù)器會(huì)返回一個(gè)包含公鑰的數(shù)字證書(shū)給客戶端饶碘;
2、 客戶端生成對(duì)稱加密密鑰并用其得到的公鑰對(duì)其加密后返回給服務(wù)器馒吴;
3熊镣、 服務(wù)器使用自己私鑰對(duì)收到的加密數(shù)據(jù)解密,得到對(duì)稱加密密鑰并保存募书;
4绪囱、 然后雙方通過(guò)對(duì)稱加密的數(shù)據(jù)進(jìn)行傳輸。

數(shù)字證書(shū):
在HTTPS客戶端與服務(wù)器第一次交互時(shí)莹捡,服務(wù)端返回給客戶端的數(shù)字證書(shū)是讓客戶端驗(yàn)證這個(gè)數(shù)字證書(shū)是不是服務(wù)端的鬼吵,證書(shū)所有者是不是該服務(wù)器,確保數(shù)據(jù)由正確的服務(wù)端發(fā)來(lái)篮赢,沒(méi)有被第三方篡改齿椅。數(shù)字證書(shū)可以保證數(shù)字證書(shū)里的公鑰確實(shí)是這個(gè)證書(shū)的所有者(Subject)的琉挖,或者證書(shū)可以用來(lái)確認(rèn)對(duì)方身份。證書(shū)由公鑰涣脚、證書(shū)主題(Subject)示辈、數(shù)字簽名(digital signature)等內(nèi)容組成。其中數(shù)字簽名就是證書(shū)的防偽標(biāo)簽遣蚀,目前使用最廣泛的SHA-RSA加密矾麻。
證書(shū)一般分為兩種:

  1. 一種是向權(quán)威認(rèn)證機(jī)構(gòu)購(gòu)買(mǎi)的證書(shū),服務(wù)端使用該種證書(shū)時(shí)芭梯,因?yàn)樘O(píng)果系統(tǒng)內(nèi)置了其受信任的簽名根證書(shū)险耀,所以客戶端不需額外的配置。為了證書(shū)安全玖喘,在證書(shū)發(fā)布機(jī)構(gòu)公布證書(shū)時(shí)甩牺,證書(shū)的指紋算法都會(huì)加密后再和證書(shū)放到一起公布以防止他人偽造數(shù)字證書(shū)。而證書(shū)機(jī)構(gòu)使用自己的私鑰對(duì)其指紋算法加密累奈,可以用內(nèi)置在操作系統(tǒng)里的機(jī)構(gòu)簽名根證書(shū)來(lái)解密贬派,以此保證證書(shū)的安全。
  2. 另一種是自己制作的證書(shū)澎媒,即自簽名證書(shū)搞乏。好處是不需要花錢(qián)購(gòu)2買(mǎi),但使用這種證書(shū)是不會(huì)受信任的旱幼,所以需要我們?cè)诖a中將該證書(shū)配置為信任證書(shū).

自簽名證書(shū)具體實(shí)現(xiàn):
我們?cè)谑褂米院灻C書(shū)來(lái)實(shí)現(xiàn)HTTPS請(qǐng)求時(shí)查描,因?yàn)椴幌駲C(jī)構(gòu)頒發(fā)的證書(shū)一樣其簽名根證書(shū)在系統(tǒng)中已經(jīng)內(nèi)置了,所以我們需要在App中內(nèi)置自己服務(wù)器的簽名根證書(shū)來(lái)驗(yàn)證數(shù)字證書(shū)柏卤。首先將服務(wù)端生成的.cer格式的根證書(shū)添加到項(xiàng)目中冬三,注意在添加證書(shū)要一定要記得勾選要添加的targets。這里有個(gè)地方要注意:蘋(píng)果的ATS要求服務(wù)端必須支持TLS 1.2或以上版本缘缚;必須使用支持前向保密的密碼勾笆;證書(shū)必須使用SHA-256或者更好的簽名hash算法來(lái)簽名,如果證書(shū)無(wú)效桥滨,則會(huì)導(dǎo)致連接失敗窝爪。由于我在生成的根證書(shū)時(shí)簽名hash算法低于其要求,在配置完請(qǐng)求時(shí)一直報(bào)NSURLErrorServerCertificateUntrusted = -1202錯(cuò)誤齐媒,希望大家可以注意到這一點(diǎn)蒲每。

那么如何在Moya中使用自簽名的證書(shū)來(lái)實(shí)現(xiàn)HTTPS網(wǎng)絡(luò)請(qǐng)求呢,請(qǐng)期待下回我專門(mén)分享......需要自定義一個(gè)Manager管理

綜合使用的方法如下

定義一個(gè)公用的Moya請(qǐng)求服務(wù)對(duì)象

let MyAPIProvider = MoyaProvider<NetAPIManager>(endpointClosure: myEndpointClosure,requestClosure: requestClosure, plugins: [NetworkLoggerPlugin(verbose: true, responseDataFormatter: JSONResponseDataFormatter),myNetworkPlugin])

// MARK: -創(chuàng)建一個(gè)Moya請(qǐng)求
func sendRequest(_ postDict: Dictionary<String, Any>? = nil,
                 success:@escaping (Dictionary<String, Any>)->(),
                 failure:@escaping (MoyaError)->()) -> Cancellable? {
    
   let request = MyAPIProvider.request(.Show) { result in    
        switch result {
        case let .success(moyaResponse):
            
            
            do {
                let any = try moyaResponse.mapJSON()
                let data =  moyaResponse.data
                let statusCode =  moyaResponse.statusCode
                MyLog("\(data) --- \(statusCode) ----- \(any)")
                
                success(["":""])
                

            } catch {
                
            }
            
           
            
        case let .failure(error):
            
            print(error)
            failure(error)
        }
    }
    
    return request
}

取消所有的Moya請(qǐng)求

// MARK: -取消所有請(qǐng)求
func cancelAllRequest() {
//    MyAPIProvider.manager.session.invalidateAndCancel()  //取消所有請(qǐng)求
    MyAPIProvider.manager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
        dataTasks.forEach { $0.cancel() }
        uploadTasks.forEach { $0.cancel() }
        downloadTasks.forEach { $0.cancel() }
    }
    
    //let sessionManager = Alamofire.SessionManager.default
    //sessionManager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
    //    dataTasks.forEach { $0.cancel() }
    //    uploadTasks.forEach { $0.cancel() }
    //    downloadTasks.forEach { $0.cancel() }
    //}

}

完畢喻括,待續(xù)更高級(jí)的用法...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邀杏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子唬血,更是在濱河造成了極大的恐慌望蜡,老刑警劉巖唤崭,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脖律,居然都是意外死亡谢肾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)小泉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)芦疏,“玉大人,你說(shuō)我怎么就攤上這事膏孟∶蟹郑” “怎么了拌汇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵柒桑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我噪舀,道長(zhǎng)魁淳,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任与倡,我火速辦了婚禮界逛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纺座。我一直安慰自己息拜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布净响。 她就那樣靜靜地躺著少欺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馋贤。 梳的紋絲不亂的頭發(fā)上赞别,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音配乓,去河邊找鬼仿滔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛犹芹,可吹牛的內(nèi)容都是我干的崎页。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼腰埂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了盐固?” 一聲冷哼從身側(cè)響起荒给,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎曙咽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體挑辆,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年洒嗤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渔隶。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖洁奈,靈堂內(nèi)的尸體忽然破棺而出间唉,到底是詐尸還是另有隱情,我是刑警寧澤利术,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布呈野,位于F島的核電站,受9級(jí)特大地震影響印叁,放射性物質(zhì)發(fā)生泄漏被冒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一轮蜕、第九天 我趴在偏房一處隱蔽的房頂上張望昨悼。 院中可真熱鬧,春花似錦肠虽、人聲如沸幔戏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闲延。三九已至,卻和暖如春韩玩,著一層夾襖步出監(jiān)牢的瞬間垒玲,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工找颓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留合愈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像佛析,于是被迫代替她去往敵國(guó)和親益老。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理寸莫,服務(wù)發(fā)現(xiàn)捺萌,斷路器,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 數(shù)字證書(shū)原理 - 無(wú)恙 - 博客園 文中首先解釋了加密解密的一些基礎(chǔ)知識(shí)和概念膘茎,然后通過(guò)一個(gè)加密通信過(guò)程的例子說(shuō)明...
    拉肚閱讀 1,657評(píng)論 0 3
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評(píng)論 25 707
  • 目錄 準(zhǔn)備 分析2.1. 三次握手2.2. 創(chuàng)建 HTTP 代理(非必要)2.3. TLS/SSL 握手2.4. ...
    RunAlgorithm閱讀 37,881評(píng)論 12 117
  • 原文地址 http://blog.csdn.net/u012409247/article/details/4985...
    0fbf551ff6fb閱讀 3,513評(píng)論 0 13