網(wǎng)絡(luò)編程
網(wǎng)絡(luò)編程簡介、基于TCP協(xié)議的網(wǎng)絡(luò)通信
網(wǎng)絡(luò)編程簡介
Android中常用的網(wǎng)絡(luò)編程有如下幾種方式:
針對(duì)HTTP協(xié)議的網(wǎng)絡(luò)編程,如HttpURLConnection或HttpClient直接使用WebKit訪問網(wǎng)絡(luò)
基于TCP協(xié)議的網(wǎng)絡(luò)通信
通信協(xié)議核心要素︰
語義
語法
時(shí)序
TCP/IP通信協(xié)議是一種可靠的、雙向的、持續(xù)的、點(diǎn)對(duì)點(diǎn)的網(wǎng)絡(luò)協(xié)議
基于TCP協(xié)議的網(wǎng)絡(luò)編程主要使用以下Socket :
ServerSocket:服務(wù)器套接字
Socket:客戶端套接字
常用的Socket的構(gòu)造方法︰
上述兩個(gè)Socket構(gòu)造方法都聲明拋出IOException異常,因此在創(chuàng)建Socket對(duì)象必須捕獲或拋出異常。最好選擇注冊(cè)端口(范圍是1024~49151的數(shù)),通常應(yīng)用程序使用這個(gè)范圍內(nèi)的端口,以防止發(fā)生沖突。
Socket(String host,int port)
Socket (String host,int port,InetAddress localAddr,int localPort)
ServerSocket類常用構(gòu)造方法︰
ServerSocket類的構(gòu)造方法都聲明拋出IOException異常,因此在創(chuàng)建ServerSocket對(duì)象時(shí)必須捕獲或拋出異常。另外,在選擇端口號(hào)時(shí),最好選擇注冊(cè)端口(范圍是1024~49151的數(shù)),通常應(yīng)用程序使用這個(gè)范圍內(nèi)的端口,以防止發(fā)生沖突。
ServerSocket(int port)
ServerSocket(int port,int backlog)
ServerSocket(int port,int backlog,InetAddress localAddr)
使用ServerSocket進(jìn)行網(wǎng)絡(luò)通信的具體步驟︰
根據(jù)指定端口實(shí)例化一個(gè)ServerSocket對(duì)象
調(diào)用ServerSocket對(duì)象的accept()方法接收客戶端發(fā)送的Socket對(duì)象
調(diào)用Socket對(duì)象的getInputStream()/getOutputStream()方法建立與客戶端進(jìn)行交互的IO流
服務(wù)器與客戶端根據(jù)一定的協(xié)議進(jìn)行交互,直到關(guān)閉連接
關(guān)閉服務(wù)器端的Socket
回到第2步,繼續(xù)監(jiān)聽下一次客戶端發(fā)送的Socket請(qǐng)求連接
URL和URLConnection
Get與Post兩種方式提交服務(wù)端數(shù)據(jù)
Get方式提交數(shù)據(jù)
?new Thread ( ){
?override
?public void run () {
?response=GetPostUtil.sendGet (
?"http ://172.20.1o.11:8888/ api/ getInfo","userName=abc&password=123") ;
?/l/發(fā)送消息通知uI線程更新uI組件
?handler.sendEmptyMessage ( 0x123) ;
?)
?}.start ( );
?Post方式提交數(shù)據(jù)
?new
?Thread() {
?@override
?public void run() {
?response=Get Postutil . sendPost ("http://
?172.20.10.11 : 8888/api /postInfo",
?"use rName=admin &password=123") ;
?/ /發(fā)送消息通知∪I線程更新uI組件
?handler . sendEmptyMessage (0x123) ;
?} .start () ;
?HttpURLConnection
獲取HttpURLConnection對(duì)象
設(shè)置HttpURLConnection屬性
釋放HttpURLConnection對(duì)象
Gson庫的使用
Gson是一個(gè)Java庫,作用是將Java對(duì)象轉(zhuǎn)換成它對(duì)應(yīng)的JSON表示
使用Gson.toJson(...)方法來進(jìn)行序列化操作
使用Gson.fromJson(...)方法來進(jìn)行反序列化操作
對(duì)象的字段可以并推薦使用private
無需使用注解指定哪些字段被包括在序列化和反序列化操作中。當(dāng)前類,和它所有父類的所有字段都是默認(rèn)包括的。
如果字段使用transient修飾,它被默認(rèn)忽略
Gson可以正確處理null值。
序列化時(shí),值為null的字段會(huì)被跳過。
反序列化時(shí),JSON中缺失的項(xiàng),其對(duì)象對(duì)應(yīng)的字段會(huì)被設(shè)為null。內(nèi)部類、匿名類等隱含的外部類的字段不包含在序列化和反序列化中。
Volley框架
Volley框架是Google發(fā)布的基于Android平臺(tái)的網(wǎng)絡(luò)通信庫
適合進(jìn)行數(shù)據(jù)量不大、通信頻繁的網(wǎng)絡(luò)操作
Volley提供以下幾個(gè)功能:
JSON、圖像等資源的異步下載
網(wǎng)絡(luò)請(qǐng)求的排序及優(yōu)先級(jí)處理
緩存和多級(jí)別取消請(qǐng)求
與Activity生命周期聯(lián)動(dòng),Activity生命周期結(jié)束時(shí)取消所有的網(wǎng)絡(luò)請(qǐng)求
Volley在性能方面適合數(shù)據(jù)量不大、通信頻繁的網(wǎng)絡(luò)操作﹔而對(duì)于大數(shù)據(jù)量的網(wǎng)絡(luò)操作,例如文件下載等,Volley的性能表現(xiàn)則非常糟糕。
使用Volley框架前,需要將Volley.jar文件導(dǎo)入到項(xiàng)目中
使用Volley框架實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求,主要有三個(gè)步驟︰
創(chuàng)建RequestQueue對(duì)象
創(chuàng)建xxxRequest對(duì)象
將xxxRequest對(duì)象添加到RequestQueue中
OkHttp第三方網(wǎng)絡(luò)庫
OkHttp是一個(gè)第三方類庫,用于android中請(qǐng)求網(wǎng)絡(luò)。
OkHttp是一個(gè)開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架,由移動(dòng)支付square公司貢獻(xiàn)(該公司還貢獻(xiàn)了Picasso和LeakCanary ) 。
OkHttp用于替代HttpUrlConnection和ApacheHttpClient(android API23里已移除HttpClient)。
OkHttp官網(wǎng): http://square.github.io/okhttp/
OkHttp源碼github地址: ( https://github.com/square/okhttp)
OkHttp在3.13.x以上的版本需要在Android 5.0+(API level 21+)和Java 1.8的環(huán)境開發(fā)。okHttp在3.12.x以及以下的版本支持Android 2.3+(API level 9+)和Java 1.7的開發(fā)環(huán)境
OkHttp3開發(fā)三部曲︰
創(chuàng)建OkHttpClient,添加配置
創(chuàng)建請(qǐng)求
執(zhí)行請(qǐng)求
創(chuàng)建OkHttpClient
一個(gè)最簡單的OkHttpClient
?okHttpClient okHttpClient=new OkHttpclient. Builder ( ) .build( );
?一個(gè)復(fù)雜點(diǎn)的OkHttpClient配置
?File cacheDir = new File(getcacheDir(), "okhttp_cache" ) ;Cache cache = new Cache (cacheDir,10 * 1024 * 1024);
?okHttpclient = new OkHttpclient.Builder ()
?.connectTimeout (5*1000,TimeUnit.MILLISECONDS)//鏈接超時(shí).readTimeout ( 10*1000 , TimeUnit.MILLISECONDS)//讀取超時(shí).writeTimeout (10*1000 , TimeUnit.MILLISECONDS)//寫入超時(shí)
?.addInterceptor (new HttpHeadInterceptor())//應(yīng)用攔截器:統(tǒng)一添加消息頭.addNetworkInterceptor(new NetworkspaceInterceptor() )//網(wǎng)絡(luò)攔截器
?.addInterceptor (loggingInterceptor)//應(yīng)用攔截器:打印日志
?.cache (cache)//設(shè)置緩存
?.build ( ) ;
?創(chuàng)建請(qǐng)求
GET請(qǐng)求
?Request req = new Request.Builder ( ) .url(url) .build ( );Call call =okHttpclient .newCall (req);
?普通POST請(qǐng)求(JSON請(qǐng)求)
?RequestBody requestBody =
?RequestBody.create (MediaType.parse ( "application/json"),jsonobject.toString () ) ;
?Request req = new Request.Builder ( ) .url(url)
?.post (requestBody)
?.build () ;
?call call = okHttpclient .newCall (req) ;
?使用FormBody傳遞鍵值對(duì)參數(shù)
?RequestBody requestBody =
?new FormBody . Builder ()
?.add ( "username" , "zhangsan").add ( "password", "1111111"").build ( ) ;
?Request req = new Request.Builder ().url(url) .post (requestBody) .build();Call call =okHttpClient.newCall (req) ;
?使用RequestBody傳遞Json對(duì)象
?OkHttpClient client = new OkHttpclient();//創(chuàng)建okHttpclient對(duì)象。//數(shù)據(jù)類型為json格式,
?MediaType JSON = MediaType.parse ( "application/json; charset=utf-8");lljson數(shù)據(jù).
?string jsonstr = "{ \"username \ ": \"lisi\ ", \"nickname \ ": \"李四\")";RequestBody body = RequestBody.create(JSON,josnstr) ;
?Request request = new Request.Builder ()
?.url ( "http: / / www.baidu . com").post (body)
?.build ( ) ;
?client.newCall (request).enqueue (new callback ( ){
?});//此處省略回調(diào)方法。
?使用RequestBody傳遞File對(duì)象
?//創(chuàng)建okHttpclient對(duì)象。
?OkHttpclient client = new OkHttpclient () ;//數(shù)據(jù)類型為json格式,
?MediaType fileType = MediaType.parse ("File/*");File file = new File ( "path" );/lfile對(duì)象.
?RequestBody body = RequestBody.create (fileType , file );Request request = new Request.Builder ()
?.url ( "http : / / www . baidu .com").post (body)
?.build ( ) ;
?client.newcall(request).enqueue (new callback() {});//此處省略回調(diào)方法。
?