開源框架學習之--網絡篇(基礎一)

本系列主要記錄學習android開發網絡請求和圖片加載框架的使用。

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

當我們開發企業級應用的時候,一般都會選擇使用已經封裝好的http框架。開源的比較流行的有:

1、volley 官方推出的網絡請求框架

下載地址: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設計

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

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

圖片加載框架:

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

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

項目地址: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 圖片緩存,包含內存和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的詳細介紹:http://www.oschina.net/p/glide

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


1. Volley簡介

除了簡單易用之外,Volley在性能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網絡操作,而對于大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。

下圖所示的這些應用都是屬于數據量不大,但網絡通信頻繁的,因此非常適合使用Volley。

StringRequest的用法

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

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

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

接下來為了要發出一條HTTP請求,我們還需要創建一個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的構造函數需要傳入三個參數,第一個參數就是目標服務器的URL地址,第二個參數是服務器響應成功的回調,第三個參數是服務器響應失敗的回調。其中,目標服務器地址我們填寫的是百度的首頁,然后在響應成功的回調里打印出服務器返回的內容,在響應失敗的回調里打印出失敗的詳細信息。

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

mQueue.add(stringRequest);

另外,由于Volley是要訪問網絡的,因此不要忘記在你的AndroidManifest.xml中添加如下權限:

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

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

1. 創建一個RequestQueue對象。

2. 創建一個StringRequest對象。

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

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

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

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

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的用法

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

至于它們的用法也基本上沒有什么特殊之處,先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);

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


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

支持HTTP2/SPDY黑科技

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

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

擁有隊列線程池,輕松寫并發

擁有Interceptors輕松處理請求與響應(比如透明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();

/**

* 在這里直接設置連接超時,靜態方法內,在構造方法被調用前就已經初始話了

*/

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? 是一個接口,? 是一個準備好的可以執行的request ? ? ? ? ? ? ? ?

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

?*/

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

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

}

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

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

?*@paramresponse? 是一個響應請求? ? ? ? ? ? ? ? ? ??

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

?*/

@Override?

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

/**

* 通過拿到response這個響應請求,然后通過body().string(),拿到請求到的數據

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

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

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

*/

? ? ? ? ? ? ?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轉為字節流

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

/**

* 在這里要加上權限? 在mainfests文件中

*/

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

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

byte[] buffer =newbyte[2048];//定義一個字節數組

int len =0;

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

fileOutputStream.write(buffer,0, len);

}

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

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

}

});

未完待續!!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容