Android Volley和Gson實現網絡數據加載android
先看接口git
1 升級接口github
http://s.meibeike.com/mcloud/ota/cloudServicejson
POST請求緩存
參數列表以下網絡
mainversion 1.0
commoninfo {"timestamp":"1450772874213","clientversion":"6.0","clientdescription":"goof","commonversion":"1.0","format":"json","clienttype":"3"}
json {"yunbangsn":"","pcode":"ncc","subversion":0,"clienttype":"3","innerversion":2015121821,"function":118}
返回信息以下session
{
"code": 0,
"type": "0",
"url": "http://d.meibeike.com/mcfs/ota/client/2015-12-18/CloudBar_2015121818_1.0.2.9.apk",
"function": 118,
"message": "成功獲取版本信息",
"displayversion": "1.0.2.9",
"filesize": 6363546,
"subversion": 0,
"innerversion": 2015121818,
"updatemsg": "1.修改投射提示「USB導入出錯」問題\r\n2.修改偶然性崩潰\r\n3.修改偶然性已綁定用戶因爲某些操做後變成了未綁定用戶,數據丟失",
"updatemsg_cn": "1.修改投射提示「USB導入出錯」問題\r\n2.修改偶然性崩潰\r\n3.修改偶然性已綁定用戶因爲某些操做後變成了未綁定用戶,數據丟失",
"md5": "727c136c7914ffa8f480bf4d2037871d",
"updatemsg_tw": null,
"forceflag": "0"
}
上代碼框架
public class MainActivity extends Activity { TextView show; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); show = (TextView)findViewById(R.id.show); Button test = (Button)findViewById(R.id.test); test.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { RequestQueue queue = MyVolley.getRequestQueue(); GsonRequestNew<Cloud103Entity> myReq = new GsonRequestNew<Cloud103Entity>(Method.POST, "http://192.168.2.33:8084/mcloud/cloudclub/cloudService", Cloud103Entity.class, createMyReqSuccessListener(), createMyReqErrorListener()){ //傳參數 protected Map<String, String> getParams() throws com.android.volley.AuthFailureError { Map<String, String> params = new HashMap<String, String>(); params.put("mainversion", "1.0"); params.put("commoninfo", getCommoninfo()); params.put("json", getJson()); Log.i("TAG", "發送參數" + params); return params; }; }; Log.i("TAG", "發送URL" + "http://192.168.2.33:8084/mcloud/cloudclub/cloudService"); queue.add(myReq); } }); } protected String getCommoninfo() { JSONObject commoninfo = new JSONObject(); try { commoninfo.put("commonversion", "1.0"); commoninfo.put("clienttype", "3"); commoninfo.put("clientversion", "6.0"); commoninfo.put("clientdescription", "goof"); commoninfo.put("timestamp", "1450765392640"); commoninfo.put("format", "json"); } catch (JSONException e) { Log.i("TAG", "e---" + e.getMessage()); } return commoninfo.toString(); } protected String getJson() { JSONObject json = new JSONObject(); try { json.put("function", 103); json.put("subversion", 0); json.put("userid", "mm730@mbk.com"); json.put("password", "e10adc3949ba59abbe56e057f20f883e"); json.put("accounttype", 0); } catch (JSONException e) { Log.i("TAG", "e---" + e.getMessage()); } return json.toString(); } private Response.Listener<Cloud103Entity> createMyReqSuccessListener() { return new Response.Listener<Cloud103Entity>() { @Override public void onResponse(Cloud103Entity response) { show.setText(response.getMessage()); } }; } private Response.ErrorListener createMyReqErrorListener() { return new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { show.setText(error.getMessage()); } }; } }
public class GsonRequestNew<T> extends Request<T> { private final Listener<T> mListener; private Gson mGson; private Class<T> mClass; public GsonRequestNew(int method, String url, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { super(method, url, errorListener); mGson = new Gson(); mClass = clazz; mListener = listener; } public GsonRequestNew(String url, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { this(Method.GET, url, clazz, listener, errorListener); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); Log.i("TAG", "響應" + jsonString); return Response.success(mGson.fromJson(jsonString, mClass), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(T response) { mListener.onResponse(response); } }
public class Cloud103Entity { private ArrayList<String> bindlist; private String message;// 返回信息 private String sessionkey;// 登陸成功後,後續操做以此sessionKey爲準 private String username; private short subversion = 0;// 業務接口協議版本號 private String email;// email號碼帳號 private long meiid;// 美貝殼內部id private int faceid;// 用戶頭像id private int code;// 返回碼 private String faceurl;// 用戶頭像url private String mobile;// 手機號碼帳號 private int function; public ArrayList<String> getBindlist() { return this.bindlist; } public void setBindlist(ArrayList<String> bindlist) { this.bindlist = bindlist; } public String getMessage() { return this.message; } public void setMessage(String message) { this.message = message; } public String getSessionkey() { return this.sessionkey; } public void setSessionkey(String sessionkey) { this.sessionkey = sessionkey; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public short getSubversion() { return this.subversion; } public void setSubversion(short subversion) { this.subversion = subversion; } public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } public long getMeiid() { return this.meiid; } public void setMeiid(long meiid) { this.meiid = meiid; } public int getFaceid() { return this.faceid; } public void setFaceid(int faceid) { this.faceid = faceid; } public int getCode() { return this.code; } public void setCode(int code) { this.code = code; } public String getFaceurl() { return this.faceurl; } public void setFaceurl(String faceurl) { this.faceurl = faceurl; } public String getMobile() { return this.mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public int getFunction() { return this.function; } public void setFunction(int function) { this.function = function; } /** * * { "bindlist": [ "C001B00010000008" ], "message": "登陸成功", "sessionkey": * "DC385A65D2FEA3FB2021F3F717B4FCD1", "username": "", "subversion": 0, * "email": "mm730@mbk.com", "meiid": 1000023, "faceid": 0, "code": 0, * "faceurl": "", "mobile": "", "function": "103" } */ }
public class MyApp extends Application{ @Override public void onCreate() { super.onCreate(); MyVolley.init(this); } }
public class MyVolley { private static RequestQueue mRequestQueue; static void init(Context context) { mRequestQueue = Volley.newRequestQueue(context); } public static RequestQueue getRequestQueue() { if (mRequestQueue != null) { return mRequestQueue; } else { throw new IllegalStateException("RequestQueue not initialized"); } } }
Code見 https://github.com/huanyi0723/VolleyGson/ide
Volley代碼剖析
Volley
和 Volley 框架同名的類,實際上是個工具類,做用是構建一個可用於添加網絡請求的 RequestQueue 對象
Request
網絡請求的抽象類。咱們經過構建一個 Request 類的非抽象子類(StringRequest、JsonRequest、ImageRequest 或自定義)對象
Volley 支持 8 種 Http 請求方式 GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, PATCH
Request 類中包含了請求 url,請求請求方式,請求 Header,請求 Body,請求的優先級等信息
子類必須重寫的兩個方法
parseNetworkResponse() //將網絡返回的原生字節內容,轉換成合適的類型
deliverResponse() //將解析成合適類型的內容傳遞給它們的監聽回調
getBody() //能夠構建用於 POST、PUT、PATCH 請求方式的 Body 內容
getParams() // getBody 函數沒有被重寫狀況下,此方法的返回值會被 key、value 分別編碼後拼裝起來轉換爲字節碼做爲 Body 內容
RequestQueue
Volley 框架的核心類,將請求 Request 加入到一個運行的 RequestQueue 中,來完成請求操做
mCacheQueue //緩存請求隊列
mNetworkQueue //網絡請求隊列
mCurrentRequests //正在進行中,還沒有完成的請求集合
mWaitingRequests //等待請求的集合
start() //開啓一個緩存調度線程 CacheDispatcher 和 n 個網絡調度線程 NetworkDispatcher ,這裏 n 默認爲 4
add() //加入請求
finish() //請求完成
cancelAll() //請求取消
CacheDispatcher
一個線程,用於調度處理走緩存的請求
mCacheQueue //緩存請求隊列
mNetworkQueue //網絡請求隊列
mCache //表明了一個能夠獲取請求結果,存儲請求結果的緩存
mDelivery //請求結果傳遞類
NetworkDispatcher
一個線程,用於調度處理走網絡的請求
mQueue //網絡請求隊列
mNetwork //網絡類,表明了一個能夠執行請求的網絡
mCache //緩存類
mDelivery //請求結果傳遞類
Cache
緩存接口,表明了一個能夠獲取請求結果,存儲請求結果的緩存
get() //經過 key 獲取請求的緩存實體
put() //存入一個請求的緩存實體
remove() //移除指定的緩存實體
clear() //清空緩存
內部類 Entry //表明緩存實體
data //請求返回的數據(Body 實體)
etag //Http 響應首部中用於緩存新鮮度驗證的 ETag
serverDate //Http 響應首部中的響應產生時間
ttl //緩存的過時時間
softTtl //緩存的新鮮時間
responseHeaders //響應的 Headers
isExpired() //判斷緩存是否過時,過時緩存不能繼續使用
refreshNeeded() //判斷緩存是否新鮮,不新鮮的緩存須要發到服務端作新鮮度的檢測
DiskBasedCache
繼承 Cache 類,基於 Disk 的緩存實現類
initialize() //初始化,掃描緩存目錄獲得全部緩存數據摘要信息放入內存
get() //從緩存中獲得數據。先從摘要信息中獲得摘要信息,而後讀取緩存數據文件獲得內容
put() //將數據存入緩存內。先檢查緩存是否會滿,會則先刪除緩存中部分數據,而後再新建緩存文件
pruneIfNeeded() //檢查是否能再分配 neededSpace 字節的空間,若是不能則刪除緩存中部分數據
remove() //移除指定的緩存實體
clear() //清空緩存
內部類CacheHeader //緩存文件摘要信息,存儲在緩存文件的頭部
NoCache
繼承 Cache 類,不作任何操做的緩存實現類,可將它做爲構建 RequestQueue 的參數以實現一個不帶緩存的請求隊列函數
Network 表明網絡的接口,處理網絡請求 performRequest() //用於執行特定請求NetworkResponse Network 中方法 performRequest 的返回值 封裝了網絡請求響應的 StatusCode,Headers 和 Body 等 statusCode //Http 響應狀態碼 data //Body 數據 headers //表示是否爲 304 響應 networkTimeMs //請求耗時 BasicNetwork Volley 中默認的網絡接口實現類。調用 HttpStack 處理請求, 並將結果轉換爲可被 ResponseDelivery 處理的 NetworkResponseHttpStack 用於處理 Http 請求,返回請求結果的接口 performRequest() //執行 Request 表明的請求,第二個參數表示發起請求以前,添加額外的請求 HeadersHttpClientStack 實現 HttpStack 接口,利用 Apache 的 HttpClient 進行各類請求方式的請求HurlStack 實現 HttpStack 接口,利用 Java 的 HttpURLConnection 進行各類請求方式的請求Response 封裝了通過解析後的數據,用於傳輸。 而且有兩個內部接口 Listener 和 ErrorListener 分別可表示請求失敗和成功後的回調。ByteArrayPool byte[] 的回收池,用於 byte[] 的回收再利用,減小了內存的分配和回收PoolingByteArrayOutputStream 繼承 ByteArrayOutputStream,原始 ByteArrayOutputStream 中用於接受寫入 bytes 的 buf, 每次空間不足時便會 new 更大容量的 byte[], 而 PoolingByteArrayOutputStream 使用了 ByteArrayPool 做爲 Byte[] 緩存來減小這種操做,從而提升性能HttpHeaderParser Http header 的解析工具類,在 Volley 中主要做用是用於解析 Header 從而判斷返回結果是否須要緩存, 若是須要返回 Header 中相關信息 parseDateAsEpoch() //解析時間,將 RFC1123 的時間格式,解析成 epoch 時間 parseCharset() //解析編碼集,在 Content-Type 首部中獲取編碼集,若是沒有找到,默認返回 ISO-8859-1 parseCacheHeaders() 經過網絡響應中的緩存控制 Header 和 Body 內容,構建緩存實體。 若是 Header 的 Cache-Control 字段含有 no-cache 或 no-store 表示不緩存,返回 nullRetryPolicy 重試策略接口 getCurrentTimeout() //獲取當前請求用時 getCurrentRetryCount() //獲取已經重試的次數 retry() //肯定是否重試DefaultRetryPolicy Volley 默認的重試策略實現類 mCurrentRetryCount //已經重試次數 mBackoffMultiplier mCurrentTimeoutMs //當前重試的 timeout 時間ResponseDelivery 請求結果的傳輸接口,用於傳遞請求結果或者請求錯誤 postResponse() //此方法用於傳遞請求結果, request 和 response 參數分別表示請求信息和返回結果信息 postResponse() //此方法用於傳遞請求結果,並在完成傳遞後執行 Runnable postError() //傳輸請求錯誤ExecutorDelivery 請求結果傳輸接口具體實現類 在 Handler 對應線程中傳輸緩存調度線程或者網絡調度線程中產生的請求結果或請求錯誤, 會在請求成功的狀況下調用 Request.deliverResponse(…) 函數,失敗時調用 Request.deliverError(…) 函數