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

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

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

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

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

下載地址: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的異步通信庫(kù)

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

4. Asynchronous Http Client for Android Android異步Http請(qǐng)求

項(xiàng)目地址:https://github.com/loopj/android-async-http

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

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

項(xiàng)目地址: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

特點(diǎn):https://code.google.com/p/android-query/#Why_AQuery?

6. Async Http Client Java異步Http請(qǐng)求

項(xiàng)目地址:https://github.com/AsyncHttpClient/async-http-client

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

7. Ion?支持圖片、json、http post等異步請(qǐng)求

項(xiàng)目地址:https://github.com/koush/ion

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

8. HttpCache Http緩存

項(xiàng)目地址: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

項(xiàng)目地址:https://github.com/kevinsawicki/http-request

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

10. okhttp square開(kāi)源的http工具類(lèi)

項(xiàng)目地址:https://github.com/square/okhttp

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

11. Retrofit RESTFUL API設(shè)計(jì)

項(xiàng)目地址:https://github.com/square/retrofit

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

圖片加載框架:

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

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

項(xiàng)目地址: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開(kāi)源的圖片緩存

項(xiàng)目地址:https://github.com/square/picasso

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

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

項(xiàng)目地址: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 快速而高效圖片加載

項(xiàng)目地址:https://github.com/facebook/fresco

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

5、bumptech/glide 圖片加載和緩存庫(kù)

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

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


1. Volley簡(jiǎn)介

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

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

StringRequest的用法

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

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

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

接下來(lái)為了要發(fā)出一條HTTP請(qǐng)求,我們還需要?jiǎng)?chuàng)建一個(gè)StringRequest對(duì)象,如下所示:

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

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

mQueue.add(stringRequest);

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

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

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

1. 創(chuàng)建一個(gè)RequestQueue對(duì)象。

2. 創(chuàng)建一個(gè)StringRequest對(duì)象。

3. 將StringRequest對(duì)象添加到RequestQueue里面。

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

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

可是這只是指定了HTTP請(qǐng)求方式是POST,那么我們要提交給服務(wù)器的參數(shù)又該怎么設(shè)置呢?很遺憾,StringRequest中并沒(méi)有提供設(shè)置POST參數(shù)的方法,但是當(dāng)發(fā)出POST請(qǐng)求的時(shí)候,Volley會(huì)嘗試調(diào)用StringRequest的父類(lèi)——Request中的getParams()方法來(lái)獲取POST參數(shù),那么解決方法自然也就有了,我們只需要在StringRequest的匿名類(lèi)中重寫(xiě)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的用法,我們?cè)賮?lái)進(jìn)階學(xué)習(xí)一下JsonRequest的用法。類(lèi)似于StringRequest,JsonRequest也是繼承自Request類(lèi)的,不過(guò)由于JsonRequest是一個(gè)抽象類(lèi),因此我們無(wú)法直接創(chuàng)建它的實(shí)例,那么只能從它的子類(lèi)入手了。JsonRequest有兩個(gè)直接的子類(lèi),JsonObjectRequest和JsonArrayRequest,從名字上你應(yīng)該能就看出它們的區(qū)別了吧?一個(gè)是用于請(qǐng)求一段JSON數(shù)據(jù)的,一個(gè)是用于請(qǐng)求一段JSON數(shù)組的。

至于它們的用法也基本上沒(méi)有什么特殊之處,先new出一個(gè)JsonObjectRequest對(duì)象,如下所示:

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);

}

});

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

mQueue.add(jsonObjectRequest);

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


2、OkHttp是一個(gè)高效的Http客戶(hù)端,有如下的特點(diǎn):

支持HTTP2/SPDY黑科技

socket自動(dòng)選擇最好路線,并支持自動(dòng)重連

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

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

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

基于Headers的緩存策略

源碼分析地址:http://www.itdecent.cn/p/aad5aacd79bf

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

基本使用

privateRequest request;

private static OkHttpClient client =new OkHttpClient();

/**

* 在這里直接設(shè)置連接超時(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請(qǐng)求同步方法

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? 是一個(gè)接口,? 是一個(gè)準(zhǔn)備好的可以執(zhí)行的request ? ? ? ? ? ? ? ?

? *? ? ? ? ? ? ? 可以取消,對(duì)位一個(gè)請(qǐng)求對(duì)象,只能單個(gè)請(qǐng)求 ? @parame ? ? ? ? ? ? ? ? ? ?

?*/

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

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

}

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

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

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

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

?*/

@Override?

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

/**

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

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

* toString()每個(gè)類(lèi)都有的,是把對(duì)象轉(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 {

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

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

/**

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

*/

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

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

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

int len =0;

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

fileOutputStream.write(buffer,0, len);

}

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

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

}

});

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評(píng)論 25 709
  • 太長(zhǎng)了,還是轉(zhuǎn)載吧...今天在看博客的時(shí)候,無(wú)意中發(fā)現(xiàn)了@Trinea在GitHub上的一個(gè)項(xiàng)目Android開(kāi)源...
    龐哈哈哈12138閱讀 20,394評(píng)論 3 283
  • 鑒于今日暴雨連續(xù),濕氣過(guò)大,中醫(yī)說(shuō)百病濕難去,但我們鄭重宣布,找到了去濕最佳辦法:五糧液+燒烤,保證能一掃身體陰霾...
    小喇叭_2e75閱讀 317評(píng)論 0 0
  • 研三在讀,物流專(zhuān)業(yè),PPT設(shè)計(jì)師。1月13日入市。 螞蟻聚寶APP,28天,本金3W,收益人民幣1336,年化60...
    武超WUCHAO閱讀 1,559評(píng)論 15 11
  • 人生就是一列開(kāi)往墳?zāi)沟牧熊?chē),路途上會(huì)有很多站。很難有人可以至始至終陪你走完,當(dāng)陪你的人要下車(chē)時(shí),即使不舍,也該心存...
    Fwx煙雨傾城閱讀 263評(píng)論 2 4

友情鏈接更多精彩內(nèi)容