訪問網路的框架(Volley和OkHttp3)使用
Volley
Volley是在Google/IO大會上提出的,使得android應用網路操作更方便快捷
Volley既可以非常簡單的訪問網路,也可以輕鬆的載入圖片,在不同的執行緒上非同步執行所有請求而避免了阻塞主執行緒
設計目標: 適合資料量不大但通訊操作頻繁的網路操作,不適合大資料量的網路操作,比如檔案下載
使用
Velloy中的RequestQueue和Request
- RequestQueue用來執行請求的請求佇列
- Request用來構造一個請求物件
Request物件主要有以下幾種型別:
- StringReqeust 響應的主體為字串
- JsonArrayReqeust 傳送和接收JSON物件
- JsonObjectRequest傳送和接收Json物件
- ImageRequest傳送和接收Image
基本使用
建立一個RequestQueue例項
//這裡的this指的是Context RequestQueue requestQueue = Volley.newRequestQueue(this);
建立一個Request(義JsonObjectRequest為例,其它幾個類似)
private final String url="http:/xxxxx"//所需url JsonObjectRequest req=new JsonObjectRequest(url,null,new Response.Listener<JsonObject>(){ @Override public void onResponse(JsonObject response){ //新增自己的響應邏輯, } }, new ResponseError.Listener(){ @Override public void onResponseError(VollerError error){ //錯誤處理 L.d("Error Message:","Error is"+error); } });
將request例項新增到requestQueue中
requestQueue.add(jsonObjectRequest);
ImageLoader
ImageLoader比ImageRequest更加高效,它不僅可以圖片進行快取,還可以過濾掉重複的連結,避免重複傳送請求。
由於ImageLoader不是繼承Request的所以它的使用傳送和以前不同,步驟如下:
建立一個RequestQueue物件
//這裡的this指的是Context RequestQueue requestQueue = Volley.newRequestQueue(this);
建立一個ImageLoader物件
ImageLoader imageLoader = new ImageLoader(mQueue, new ImageCache() { @Override public void putBitmap(String url, Bitmap bitmap) { } @Override public Bitmap getBitmap(String url) { return null; } });
獲取一個ImageListerner物件
ImageListener listener = ImageLoader.getImageListener(imageView, R.drawable.default_image, R.drawable.failed_image);
呼叫ImageLoader的get()方法載入網路上的圖片
imageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", listener); //過載 mageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", listener, 200, 200);
為了很好的快取圖片,藉助Android提供的LruCache功能,建立一個ImageCache
新建一個BitmapCache並實現ImageCache介面
public class BitmapCache implements ImageCache { private LruCache<String, Bitmap> mCache; public BitmapCache() { int maxSize = 10 * 1024 * 1024; mCache = new LruCache<String, Bitmap>(maxSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight(); } }; } @Override public Bitmap getBitmap(String url) { return mCache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { mCache.put(url, bitmap); } }
NetworkImageView的用法
除了ImageReqeust和ImageLoader外,Volley還提供了NetworkImageView。NetworkImageView是一個自定義控制,它繼承自ImageView,具備ImageView控制元件的所有功能,並且在原生的基礎之上加入了載入網路圖片的功能。NetworkImageView控制元件的用法簡單,步驟如下:
- 建立一個RequestQueue物件
- 建立一個ImageLoader物件
- 在佈局檔案中新增一個NetworkImageView控制元件
- 在程式碼中獲取該控制元件的例項
- 設定要載入的圖片地址
其中,第一第二步和ImageLoader的用法是完全一樣的,因此這裡我們就從第三步開始學習了。首先修改佈局檔案中的程式碼,在裡面加入NetworkImageView控制元件,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send Request" /> <com.android.volley.toolbox.NetworkImageView android:id="@+id/network_image_view" android:layout_width="200dp" android:layout_height="200dp" android:layout_gravity="center_horizontal" /> </LinearLayout>
接著在Activity獲取到這個控制元件的例項,這就非常簡單了,程式碼如下所示:
networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);
得到了NetworkImageView控制元件的例項之後,我們可以呼叫它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法來分別設定載入中顯示的圖片,載入失敗時顯示的圖片,以及目標圖片的URL地址,如下所示:
networkImageView.setDefaultImageResId(R.drawable.default_image); networkImageView.setErrorImageResId(R.drawable.failed_image); networkImageView.setImageUrl("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", imageLoader);
關閉
如果在一個Activity裡面啟動了網路請求,而在這個網路請求還沒返回結果的時候,如果Activity被結束了,則我們需要寫如下程式碼作為防守:
@Override public void onPostExecute(Result r) { if (getActivity() == null) { return; } // ... }
Activity被終止之後,如果繼續使用其中的Context等,除了無辜的浪費CPU,電池,網路等資源,有可能還會導致程式crash,所以,我們需要處理這種一場情況。
使用Volley的話,我們可以在Activity停止的時候,同時取消所有或部分未完成的網路請求。
Volley裡所有的請求結果會返回給主程序,如果在主程序裡取消了某些請求,則這些請求將不會被返回給主執行緒。
比如,可以針對某些個request做取消操作:@Override public void onStop() { for (Request <?> req : mInFlightRequests) { req.cancel(); } ... }
或者,取消這個佇列裡的所有請求:
@Override pubic void onStop() { mRequestQueue.cancelAll(this); ... }
也可以根據RequestFilter或者Tag來終止某些請求:
@Override public void onStop() { mRequestQueue.cancelAll( new RequestFilter() {}) ... // or mRequestQueue.cancelAll(new Object()); ... }
OkHttp3
Android Studio 配置gradle環境:
compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.squareup.okio:okio:1.11.0'
新增網路許可權
<uses-permission android:name="android.permission.INTERNET"/>
使用教程
Http Get
非同步的Get
在Http請求中最常見的就是get方法了,在大多數的使用場景中,我們使用的都是非同步的Get請求
// step 1: 建立 OkHttpClient 物件 OkHttpClient okHttpClient = new OkHttpClient(); // step 2: 建立一個請求,不指定請求方法時預設是GET。 Request.Builder requestBuilder = new Request.Builder().url("http://www.baidu.com"); //可以省略,預設是GET請求 requestBuilder.method("GET",null); // step 3:建立 Call 物件 Call call = okHttpClient.newCall(requestBuilder.build()); //step 4: 開始非同步請求 call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // TODO: 17-1-4 請求失敗 } @Override public void onResponse(Call call, Response response) throws IOException { // TODO: 17-1-4 請求成功 //獲得返回體 ResponseBody body = response.body(); } });
檔案下載
//step 1: 不變的第一步建立 OkHttpClick OkHttpClient okHttpClient = new OkHttpClient(); //step 2: 建立Requset Request request = new Request.Builder() .url("http://www.ssyer.com/uploads/org_2017010593503_775.jpg") .build(); //step 3:建立聯絡,建立Call mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) { InputStream inputStream = response.body().byteStream(); FileOutputStream fileOutputStream = null; try { File file = new File(Environment.getExternalStorageDirectory() + "大獅子.jpg"); fileOutputStream = new FileOutputStream(file); byte[] buffer = new byte[2048]; int len = 0; while ((len = inputStream.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, len); } fileOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } Log.d("downloadAsynFile", "檔案下載成功"); } });
同步的Get
當然 Get 也支援阻塞方式的同步請求,不過在開發中這種方法很少被使用。上面我們也說了Call有一個 execute() 方法,你也可以直接呼叫 call.execute() 返回一個 Response 。然後利用 isSuccessful() 判讀是否成功,進行相應的結果解析。
非同步的Http Post
Post 上傳鍵值對
//step 1: 同樣的需要建立一個OkHttpClick物件 OkHttpClient okHttpClient = new OkHttpClient(); //step 2: 建立 FormBody.Builder FormBody formBody = new FormBody.Builder() .add("name", "dsd") .build(); //step 3: 建立請求 Request request = new Request.Builder().url("http://www.baidu.com") .post(formBody) .build(); //step 4: 建立聯絡 建立Call物件 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // TODO: 17-1-4 請求失敗 } @Override public void onResponse(Call call, Response response) throws IOException { // TODO: 17-1-4 請求成功 } });
在使用 Post 的時候,引數是包含在請求體中的。所以我們通過 FormBody ,新增多個String鍵值對,然後為 Request 新增 post(formBody) 完成我們 Request 的構造。之後的步驟就和Get的步驟一樣了,是不是很簡單啊!
Post非同步上傳檔案
// step 1: 建立 OkHttpClient 物件 OkHttpClient okHttpClient = new OkHttpClient(); //step 2:建立 RequestBody 以及所需的引數 //2.1 獲取檔案 File file = new File(Environment.getExternalStorageDirectory() + "test.txt"); //2.2 建立 MediaType 設定上傳檔案型別 MediaType MEDIATYPE = MediaType.parse("text/plain; charset=utf-8"); //2.3 獲取請求體 RequestBody requestBody = RequestBody.create(MEDIATYPE, file); //step 3:建立請求 Request request = new Request.Builder().url("http://www.baidu.com") .post(requestBody) .build(); //step 4 建立聯絡 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // TODO: 17-1-4 請求失敗 } @Override public void onResponse(Call call, Response response) throws IOException { // TODO: 17-1-4 請求成功 } }); //新增許可權 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> --------------------------------------------------------------------------- 引數 說明 text/html HTML格式 text/plain 純文字格式 text/xml XML格式 image/gif gif圖片格式 image/jpeg jpg圖片格式 image/png png圖片格式 application/xhtml+xml XHTML格式 application/xml XML資料格式 application/atom+xml Atom XML聚合格式 application/json JSON資料格式 application/pdf pdf格式 application/msword Word文件格式 application/octet-stream 二進位制流資料