編輯:關於Android編程
本文github地址:
https://github.com/YoungBear/MyBlog/blob/master/VolleyLearn.md
Volley是Android下個一個網絡請求庫,它可以讓Android下的網絡訪問更加簡單和快速。默認情況下,Volley都是異步訪問網絡的,所以我們不必擔心異步處理問題。
在build.gradle中添加dependency:
dependencies { ... compile 'com.android.volley:volley:1.0.0' }
使用源代碼,作為一個library project。
git clone https://android.googlesource.com/platform/frameworks/volley
另外,也可以在源代碼中導出jar包,使用jar包作為庫。
首先,在AndroidManifest.xml中添加網絡訪問權限,
//VolleyController.java public class VolleyController { public static final String TAG = VolleyController.class.getSimpleName(); private static volatile VolleyController mInstance; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; private static Context mContext; private VolleyController(Context context) { mContext = context.getApplicationContext(); mRequestQueue = Volley.newRequestQueue(mContext); mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache()); } public static VolleyController getInstance(Context context) { if (mInstance == null) { synchronized (VolleyController.class) { if (mInstance == null) { mInstance = new VolleyController(context); } } } return mInstance; } public RequestQueue getRequestQueue() { return mRequestQueue; } public ImageLoader getImageLoader() { return mImageLoader; } publicvoid addToRequestQueue(Request req, String tag) { req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); mRequestQueue.add(req); } public void addToRequestQueue(Request req) { req.setTag(TAG); mRequestQueue.add(req); } public void cancelPendingRequests(Object tag) { if (mRequestQueue != null) { mRequestQueue.cancelAll(tag); } } }
還需要一個Cache來存放請求的圖片:
//LruBitmapCache.java public class LruBitmapCache extends LruCacheimplements ImageLoader.ImageCache{ public static int getDefaultLruCacheSize() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; return cacheSize; } public LruBitmapCache() { this(getDefaultLruCacheSize()); } public LruBitmapCache(int sizeInKiloBytes) { super(sizeInKiloBytes); } @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight() / 1024; } @Override public Bitmap getBitmap(String url) { return get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { put(url, bitmap); } }
新建一個Request並且把他加入到請求隊列中RequestQueue:
private void simpleRequest() { StringRequest stringRequest = new StringRequest( Request.Method.GET, TEST_URL, new Response.Listener() { @Override public void onResponse(String response) { Log.d(TAG, "onResponse, response: " + response); txtDisplay.setText("Response is: " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.d(TAG, "onErrorResponse, error: " + error.getMessage()); txtDisplay.setText("That didn't work!"); } }); VolleyController.getInstance(this).addToRequestQueue(stringRequest, TAG); }
Volley工作原理圖
在Activity的onStZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcCgpt723qNbQY2FuY2Vsy/nT0LHqvMfOqrjDVEFHtcTH68fzo7o8L3N0cm9uZz48L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> @Override protected void onStop() { super.onStop(); VolleyController.getInstance(this).cancelPendingRequests(TAG); }
創建POST請求
上面說的都是GET請求,下面來說一下POST請求,與GET請求不同的是,只要在創建請求的時候將請求類型改為POST請求,並且override Request的getParams方法即可。
添加請求頭部信息
override Request的getHeaders方法。
private void simplePostRequest() { StringRequest stringRequest = new StringRequest( Request.Method.POST, TEST_URL, new Response.Listener() { @Override public void onResponse(String response) { Log.d(TAG, "post, onResponse, response: " + response); txtDisplay.setText("Response is: " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.d(TAG, "post, onErrorResponse, error: " + error.getMessage()); txtDisplay.setText("That didn't work!"); } } ) { @Override protected Map getParams() throws AuthFailureError { Map params = new HashMap (); params.put("name", "Androidhive"); params.put("email", "abc@androidhive.info"); params.put("password", "password123"); return params; } @Override public Map getHeaders() throws AuthFailureError { HashMap headers = new HashMap (); headers.put("Content-Type", "application/json"); headers.put("apiKey", "xxxxxxxxxxxxxxx"); return headers; } }; //關閉Cache stringRequest.setShouldCache(false); VolleyController.getInstance(this).addToRequestQueue(stringRequest, TAG); }
Volley庫中自帶了NetworkImageView類,這個ImageView可以自動使用volley下載圖片。
private void imageRequest() { ImageRequest imageRequest = new ImageRequest( TEST_URL_1, new Response.Listener() { @Override public void onResponse(Bitmap response) { mImageView.setImageBitmap(response); } }, 0, 0, null, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.d(TAG, "onErrorResponse, error: " + error.getMessage()); } } ); VolleyController.getInstance(this).addToRequestQueue(imageRequest, TAG); }
ImageRequest構造函數源代碼:
@Deprecated public ImageRequest(String url, Response.Listenerlistener, int maxWidth, int maxHeight, Config decodeConfig, Response.ErrorListener errorListener) { this(url, listener, maxWidth, maxHeight, ScaleType.CENTER_INSIDE, decodeConfig, errorListener); }
可以看到,ImageRequest的構造函數接收6個參數
第一個參數是圖片的URL地址 第二個參數是圖片請求成功的回調,這裡我們把返回的Bitmap參數設置到ImageView中 第三和第四個參數分別用於指定允許圖片最大的寬度和高度,如果指定的網絡圖片的寬度或高度大於這裡的最大值,則會對圖片進行壓縮,指定成0的話就表示不管圖片有多大,都不進行壓縮。 第五個參數用於指定圖片的顏色屬性,Bitmap.Config下的幾個常量都可以在這裡使用,其中ARGB_8888可以展示最好的顏色屬性,每個圖片像素占據4個人字節的大小,而RGB_565則表示每個圖片像素占據2個字節大小。 第六個參數是圖片請求失敗的回調,我們可以在請求失敗時顯示一張失敗的圖片。ImageLoader也可以用於加載網絡上的圖片,並且它的內部也是使用ImageRequest來實現的,不過ImageLoader明顯要比ImageRequest更加高效,因為它不僅可以幫我們對圖片進行緩存,還可以過濾掉重復的鏈接,避免重復發送請求。
由於ImageLoader已經不是繼承自Request的了,所以它的用法也和我們之前學到的內容有所不同,總結起來大致可以分為以下四步:
創建一個RequestQueue對象 創建一個ImageLoader對象 獲取一個ImageListener對象 調用ImageLoader的get()方法加載網絡上的圖片private void imageLoaderGet() { ImageLoader imageLoader = VolleyController.getInstance(this).getImageLoader(); imageLoader.get(TEST_URL_3, new ImageLoader.ImageListener() { @Override public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) { mImageView3.setImageBitmap(response.getBitmap()); } @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Image Load Error: " + error.getMessage()); } }); }
NetworkImageView是一個自定義控件,它是繼承自ImageView的,具備ImageView控件的所有功能,並且在原生的基礎之上加入了加載網絡圖片的功能。
使用方法:
在布局文件中添加NetworkImageView 獲取ImageLoader 調用NetworkImageView的setImageUrl()方法//...mNetworkImageView = (NetworkImageView) findViewById(R.id.network_img_display); private void setNetworkImageView() { ImageLoader imageLoader = VolleyController.getInstance(this).getImageLoader(); mNetworkImageView.setImageUrl(TEST_URL_2, imageLoader); }
private void jsonRequest() { JsonObjectRequest jsonObjectRequest = new JsonObjectRequest( Request.Method.GET, TEST_URL, null, new Response.Listener() { @Override public void onResponse(JSONObject response) { txtDisplay.setText(response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse, error: " + error.getMessage()); } }); VolleyController.getInstance(this).addToRequestQueue(jsonObjectRequest, TAG); } private void jsonArrayRequest() { JsonArrayRequest jsonArrayRequest = new JsonArrayRequest( Request.Method.GET, TEST_URL2, null, new Response.Listener () { @Override public void onResponse(JSONArray response) { txtDisplay.setText(response.length() + "\n" + response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse, error: " + error.getMessage()); } } ); VolleyController.getInstance(this).addToRequestQueue(jsonArrayRequest, TAG); }
在build.gradle文件中添加gson依賴:
dependencies { ... compile 'com.google.code.gson:gson:2.7' }
自定義GsonRequest:
//GsonRequest.java public class GsonRequestextends Request { private final Gson gson = new Gson(); private final Class clazz; private final Map headers; private final Response.Listener listener; public GsonRequest(String url, Class clazz, Map headers, Listener listener, ErrorListener errorListener) { super(Method.GET, url, errorListener); this.clazz = clazz; this.headers = headers; this.listener = listener; } @Override public Map getHeaders() throws AuthFailureError { return headers != null ? headers : super.getHeaders(); } @Override protected Response parseNetworkResponse(NetworkResponse response) { try { String json = new String( response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success( gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(T response) { listener.onResponse(response); } }
在實際調用的時候,和普通的請求類似:
private void personRequest() { GsonRequestgsonRequest = new GsonRequest ( TEST_URL, Person.class, null, new Response.Listener () { @Override public void onResponse(Person response) { txtDisplay.setText("size: " + response.getContacts().size()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse, error: " + error.getMessage()); } } ); VolleyController.getInstance(this).addToRequestQueue(gsonRequest, TAG); }
實體類Person類:(在AS下可以使用gson插件來生成)
package com.example.volleylearn.model; import java.util.List; /** * Created by youngbear on 16/10/18. */ public class Person { /** * id : c200 * name : Ravi Tamada * email : ravi@gmail.com * address : xx-xx-xxxx,x - street, x - country * gender : male * phone : {"mobile":"+91 0000000000","home":"00 000000","office":"00 000000"} */ private Listcontacts; public List getContacts() { return contacts; } public void setContacts(List contacts) { this.contacts = contacts; } public static class ContactsBean { private String id; private String name; private String email; private String address; private String gender; /** * mobile : +91 0000000000 * home : 00 000000 * office : 00 000000 */ private PhoneBean phone; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public PhoneBean getPhone() { return phone; } public void setPhone(PhoneBean phone) { this.phone = phone; } public static class PhoneBean { private String mobile; private String home; private String office; public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getHome() { return home; } public void setHome(String home) { this.home = home; } public String getOffice() { return office; } public void setOffice(String office) { this.office = office; } } } }
測試代碼位置:https://github.com/YoungBear/VolleyLearn
一、配置NDK環境第一步:在AndroidStudio中配置ndk環境需要下載ndk包,在AndroidStudio中File-->ProjectStructure
學習從模仿開始一個星期完成的音樂播放器基本功能,具有下一首,上一首,暫停和隨機、順序和單曲等播放,以及保存上一次播放的狀態,缺少了歌詞顯示功能。使用了andbase框架的
事件分發是Android中非常重要的機制,是用戶與界面交互的基礎。這篇文章將通過示例打印出的Log,繪制出事件分發的流程圖,讓大家更容易的去理解Android的事件分發機
本文實例講述了Android編程單選項框RadioGroup用法。分享給大家供大家參考,具體如下:今天介紹的是RadioGroup 的組事件.RadioGroup 可將各