開源框架學(xué)習(xí)之--網(wǎng)絡(luò)篇(基礎(chǔ)一)

本系列主要記錄學(xué)習(xí)android開發(fā)網(wǎng)絡(luò)請求和圖片加載框架的使用。

網(wǎng)絡(luò)操作時官方一般都會介紹HttpClient以及HttpConnection這兩個包。前者是apache的開源庫,后者是android自帶的api。二者進行一個比較,谷歌在官方文檔已經(jīng)說明了,建議在2.3以及以上版本使用 HttpConnection。具體原因呢,是因為對2.1和2.2版本,HttpURLConnection有那么幾個Bug,所以建議用Apache 的HTTP Client;之后的版本,建議用HttpURLConnection。android 開發(fā)團隊不應(yīng)該維護該庫而是轉(zhuǎn)投更為輕量級的httpurlconnection。

當(dāng)我們開發(fā)企業(yè)級應(yīng)用的時候,一般都會選擇使用已經(jīng)封裝好的http框架。開源的比較流行的有:

1、volley 官方推出的網(wǎng)絡(luò)請求框架

下載地址:https://android.googlesource.com/platform/frameworks/volley

2、loopj/android-async-http

下載地址:https://github.com/loopj/android-async-http

官方文檔:http://loopj.com/android-async-http/

demo地址:https://github.com/loopj/android-async-http/tree/1.4.9/sample/src/main/java/com/loopj/android/http/sample

3、koush/AndroidAsync 基于nio的異步通信庫

下載地址:https://github.com/koush/AndroidAsync

4. Asynchronous Http Client for Android Android異步Http請求

項目地址:https://github.com/loopj/android-async-http

文檔介紹:http://loopj.com/android-async-http/

5. android-query 異步加載,更少代碼完成Android加載

項目地址:https://github.com/androidquery/androidqueryhttps://code.google.com/p/android-query/

文檔介紹:https://code.google.com/p/android-query/#Why_AQuery?

Demo地址:https://play.google.com/store/apps/details?id=com.androidquery

特點:https://code.google.com/p/android-query/#Why_AQuery?

6. Async Http Client Java異步Http請求

項目地址:https://github.com/AsyncHttpClient/async-http-client

文檔介紹:http://sonatype.github.io/async-http-client/

7. Ion?支持圖片、json、http post等異步請求

項目地址:https://github.com/koush/ion

文檔介紹:https://github.com/koush/ion#more-examples

8. HttpCache Http緩存

項目地址:https://github.com/Trinea/AndroidCommon

Demo地址:https://github.com/Trinea/TrineaDownload/blob/master/TrineaAndroidDemo.apk?raw=true

Demo代碼:https://github.com/Trinea/AndroidDemo/blob/master/src/cn/trinea/android/demo/HttpCacheDemo.java

9. Http Request

項目地址:https://github.com/kevinsawicki/http-request

文檔介紹:https://github.com/kevinsawicki/http-request#examples

10. okhttp square開源的http工具類

項目地址:https://github.com/square/okhttp

文檔介紹:http://square.github.io/okhttp/

11. Retrofit RESTFUL API設(shè)計

項目地址:https://github.com/square/retrofit

文檔介紹:http://square.github.io/retrofit/

圖片加載框架:

1. Android-Universal-Image-Loader 圖片緩存

目前使用最廣泛的圖片緩存,支持主流圖片緩存的絕大多數(shù)特性。

項目地址:https://github.com/nostra13/Android-Universal-Image-Loader

Demo地址:https://github.com/Trinea/TrineaDownload/blob/master/universal-imageloader-demo.apk?raw=true

文檔介紹:http://www.intexsoft.com/blog/item/74-universal-image-loader-part-3.html


2. picasso square開源的圖片緩存

項目地址:https://github.com/square/picasso

文檔介紹:http://square.github.io/picasso/

3. ImageCache 圖片緩存,包含內(nèi)存和Sdcard緩存

項目地址:https://github.com/Trinea/AndroidCommon

Demo地址:https://github.com/Trinea/TrineaDownload/blob/master/TrineaAndroidDemo.apk?raw=true

文檔介紹:http://www.trinea.cn/?p=704

4、facebook/fresco 快速而高效圖片加載

項目地址:https://github.com/facebook/fresco

文檔介紹:https://code.facebook.com/posts/366199913563917(譯文: ? ? ? ? ? ? ? http://android.jobbole.com/80922/)

5、bumptech/glide 圖片加載和緩存庫

Glide的詳細(xì)介紹:http://www.oschina.net/p/glide

Glide的下載地址:https://github.com/bumptech/glide


1. Volley簡介

除了簡單易用之外,Volley在性能方面也進行了大幅度的調(diào)整,它的設(shè)計目標(biāo)就是非常適合去進行數(shù)據(jù)量不大,但通信頻繁的網(wǎng)絡(luò)操作,而對于大數(shù)據(jù)量的網(wǎng)絡(luò)操作,比如說下載文件等,Volley的表現(xiàn)就會非常糟糕。

下圖所示的這些應(yīng)用都是屬于數(shù)據(jù)量不大,但網(wǎng)絡(luò)通信頻繁的,因此非常適合使用Volley。

StringRequest的用法

前面已經(jīng)說過,Volley的用法非常簡單,那么我們就從最基本的HTTP通信開始學(xué)習(xí)吧,即發(fā)起一條HTTP請求,然后接收HTTP響應(yīng)。首先需要獲取到一個RequestQueue對象,可以調(diào)用如下方法獲取到:

RequestQueue?mQueue?=?Volley.newRequestQueue(context);

注意這里拿到的RequestQueue是一個請求隊列對象,它可以緩存所有的HTTP請求,然后按照一定的算法并發(fā)地發(fā)出這些請求。RequestQueue內(nèi)部的設(shè)計就是非常合適高并發(fā)的,因此我們不必為每一次HTTP請求都創(chuàng)建一個RequestQueue對象,這是非常浪費資源的,基本上在每一個需要和網(wǎng)絡(luò)交互的Activity中創(chuàng)建一個RequestQueue對象就足夠了。

接下來為了要發(fā)出一條HTTP請求,我們還需要創(chuàng)建一個StringRequest對象,如下所示:

StringRequest?stringRequest?=new StringRequest("http://www.baidu.com",

new Response.Listener()?{

@Override

public voidon Response(String?response)?{

Log.d("TAG",?response);

}

},new Response.ErrorListener()?{

@Override

public void onErrorResponse(VolleyError?error)?{

Log.e("TAG",?error.getMessage(),?error);

}

});

可以看到,這里new出了一個StringRequest對象,StringRequest的構(gòu)造函數(shù)需要傳入三個參數(shù),第一個參數(shù)就是目標(biāo)服務(wù)器的URL地址,第二個參數(shù)是服務(wù)器響應(yīng)成功的回調(diào),第三個參數(shù)是服務(wù)器響應(yīng)失敗的回調(diào)。其中,目標(biāo)服務(wù)器地址我們填寫的是百度的首頁,然后在響應(yīng)成功的回調(diào)里打印出服務(wù)器返回的內(nèi)容,在響應(yīng)失敗的回調(diào)里打印出失敗的詳細(xì)信息。

最后,將這個StringRequest對象添加到RequestQueue里面就可以了,如下所示:

mQueue.add(stringRequest);

另外,由于Volley是要訪問網(wǎng)絡(luò)的,因此不要忘記在你的AndroidManifest.xml中添加如下權(quán)限:

好了,就是這么簡單,如果你現(xiàn)在運行一下程序,并發(fā)出這樣一條HTTP請求,就會看到LogCat中會打印出如下圖所示的數(shù)據(jù)。

這樣的話,一個最基本的HTTP發(fā)送與響應(yīng)的功能就完成了。你會發(fā)現(xiàn)根本還沒寫幾行代碼就輕易實現(xiàn)了這個功能,主要就是進行了以下三步操作:

1. 創(chuàng)建一個RequestQueue對象。

2. 創(chuàng)建一個StringRequest對象。

3. 將StringRequest對象添加到RequestQueue里面。

不過大家都知道,HTTP的請求類型通常有兩種,GET和POST,剛才我們使用的明顯是一個GET請求,那么如果想要發(fā)出一條POST請求應(yīng)該怎么做呢?StringRequest中還提供了另外一種四個參數(shù)的構(gòu)造函數(shù),其中第一個參數(shù)就是指定請求類型的,我們可以使用如下方式進行指定:

StringRequest?stringRequest?=newStringRequest(Method.POST,?url,??listener,?errorListener);

可是這只是指定了HTTP請求方式是POST,那么我們要提交給服務(wù)器的參數(shù)又該怎么設(shè)置呢?很遺憾,StringRequest中并沒有提供設(shè)置POST參數(shù)的方法,但是當(dāng)發(fā)出POST請求的時候,Volley會嘗試調(diào)用StringRequest的父類——Request中的getParams()方法來獲取POST參數(shù),那么解決方法自然也就有了,我們只需要在StringRequest的匿名類中重寫getParams()方法,在這里設(shè)置POST參數(shù)就可以了,代碼如下所示:

StringRequest?stringRequest?=new ?StringRequest(Method.POST,?url,??listener,?errorListener)?{

@Override

protected Map?getParams() throws AuthFailureError?{

Map?map?=newHashMap();

map.put("params1","value1");

map.put("params2","value2");

returnmap;

}

};

?JsonRequest的用法

學(xué)完了最基本的StringRequest的用法,我們再來進階學(xué)習(xí)一下JsonRequest的用法。類似于StringRequest,JsonRequest也是繼承自Request類的,不過由于JsonRequest是一個抽象類,因此我們無法直接創(chuàng)建它的實例,那么只能從它的子類入手了。JsonRequest有兩個直接的子類,JsonObjectRequest和JsonArrayRequest,從名字上你應(yīng)該能就看出它們的區(qū)別了吧?一個是用于請求一段JSON數(shù)據(jù)的,一個是用于請求一段JSON數(shù)組的。

至于它們的用法也基本上沒有什么特殊之處,先new出一個JsonObjectRequest對象,如下所示:

JsonObjectRequest?jsonObjectRequest?=new JsonObjectRequest(url,null,

newResponse.Listener()?{

@Override

public voidon Response(JSONObject?response)?{

Log.d("TAG",?response.toString());

}

},newResponse.ErrorListener()?{

@Override

public void onErrorResponse(VolleyError?error)?{

Log.e("TAG",?error.getMessage(),?error);

}

});

最后再將這個JsonObjectRequest對象添加到RequestQueue里就可以了,如下所示:

mQueue.add(jsonObjectRequest);

由此可以看出,服務(wù)器返回給我們的數(shù)據(jù)確實是JSON格式的,并且onResponse()方法中攜帶的參數(shù)也正是一個JSONObject對象,之后只需要從JSONObject對象取出我們想要得到的那部分?jǐn)?shù)據(jù)就可以了。


2、OkHttp是一個高效的Http客戶端,有如下的特點:

支持HTTP2/SPDY黑科技

socket自動選擇最好路線,并支持自動重連

擁有自動維護的socket連接池,減少握手次數(shù)

擁有隊列線程池,輕松寫并發(fā)

擁有Interceptors輕松處理請求與響應(yīng)(比如透明GZIP壓縮,LOGGING)

基于Headers的緩存策略

源碼分析地址:http://www.lxweimin.com/p/aad5aacd79bf

使用教程:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html

基本使用

privateRequest request;

private static OkHttpClient client =new OkHttpClient();

/**

* 在這里直接設(shè)置連接超時,靜態(tài)方法內(nèi),在構(gòu)造方法被調(diào)用前就已經(jīng)初始話了

*/

static{

client.newBuilder().connectTimeout(10, TimeUnit.SECONDS);

client.newBuilder().readTimeout(10, TimeUnit.SECONDS);

client.newBuilder().writeTimeout(10, TimeUnit.SECONDS);

}

//get請求同步方法

new Thread( new ?Runnable ( ) {

? ? @Override

? ? ? public void run( ) {

? ? ? ? ? ? try{

? ? ? ? ? ? ? ? request =new Request.Builder( ).url(Contants.SYNC_URL).build( );

? ? ? ? ? ? ? ? ?Response response = client.newCall(request).execute( );

? ? ? ? ? ? ? ? ?result = response.body( ).string( );

? ? ? ? ? ? ? ? ?runOnUiThread(new Runnable( ) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override ?public ?void ?run( ) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tvtext.setText(result);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.d("MainActivity","hello");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ?});

? ? ? ? ? ? ? ? }catch(Exception e) {

? ? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

? ? }

?}).start();


//異步GET:

new ? Thread( ?new Runnable( ) {

@Override public void run( ) {

? ? ? ? request =new Request.Builder().url(Contants.ASYNC_URL).build( );

? ? ? ? client.newCall(request).enqueue(new Callback() {

/**? ? ? ? ? ? ? ? ? ?

?* A call is a request that has been prepared for execution. A call can be canceled. As ? ? ? this object? ? ? ? ? ? ? ? ? ?

?* represents a single request/response pair (stream), it cannot be executed twice. ? ? ? ? ? ? ? ? ??

? *@paramcall? 是一個接口,? 是一個準(zhǔn)備好的可以執(zhí)行的request ? ? ? ? ? ? ? ?

? *? ? ? ? ? ? ? 可以取消,對位一個請求對象,只能單個請求 ? @parame ? ? ? ? ? ? ? ? ? ?

?*/

@Override public void onFailure(Call call, IOException e) {

? ? ? ? ? ? ? ? ? ? ? ? Log.d("MainActivity","請求失敗");

}

/**? ? ? ? ? ? ? ? ??

?*@paramcall? ? ? ? ? ? ? ? ? ?

?*@paramresponse? 是一個響應(yīng)請求? ? ? ? ? ? ? ? ? ??

*@throwsIOException? ? ? ? ? ? ? ? ? ??

?*/

@Override?

public void onResponse(Call call, Response response)throws IOException {

/**

* 通過拿到response這個響應(yīng)請求,然后通過body().string(),拿到請求到的數(shù)據(jù)

* 這里最好用string()? 而不要用toString()

* toString()每個類都有的,是把對象轉(zhuǎn)換為字符串

* string()是把流轉(zhuǎn)為字符串

*/

? ? ? ? ? ? ?result = response.body().string();

? ? ? ? ? ? ?runOnUiThread(new?Runnable() {

? ? ? ? ? ? ? ? ? ? ?@Override

? ? ? ? ? ? ? ? ? ? public void run( ) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tvtext.setText(result);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? });

? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? });

? ? ? ?}

}).start();

//文件下載地址

String url ="your_URL";

request =new Request.Builder().url(url).build();

OkHttpClient client =newOkHttpClient();

client.newCall(request).enqueue(new Callback() {

? ? ? ? ? ? ? ?@Override

? ? ? ? ? ? ? public void onFailure(Call call, IOException e) {

? ? ? ? ? ? ? }

@Override

public void onResponse(Call call, Response response)throws IOException {

//把請求成功的response轉(zhuǎn)為字節(jié)流

InputStream inputStream = response.body().byteStream();

/**

* 在這里要加上權(quán)限? 在mainfests文件中

*/

//在這里用到了文件輸出流

FileOutputStream fileOutputStream =newFileOutputStream(newFile("/sdcard/logo.jpg"));

byte[] buffer =newbyte[2048];//定義一個字節(jié)數(shù)組

int len =0;

while((len = inputStream.read(buffer)) != -1) {//寫出到文件

fileOutputStream.write(buffer,0, len);

}

fileOutputStream.flush();//關(guān)閉輸出流

Log.d("wuyinlei","文件下載成功...");

}

});

未完待續(xù)!!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,990評論 2 374

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