Android 学习笔记之Volley开源框架解析(一)
PS:看完了LGD的六場比賽...讓人心酸...
?
學(xué)習(xí)內(nèi)容:
1.Http請(qǐng)求的過程...
2.Volley的簡單介紹...
?
1.Http請(qǐng)求...
? 這里只是簡單的說一下Http請(qǐng)求的過程...非常的簡單...首先是發(fā)送Request..然后服務(wù)器在獲取到Request請(qǐng)求后會(huì)對(duì)其進(jìn)行相應(yīng)的處理,然后以Response的形式進(jìn)行返回,然后分配Response,即誰發(fā)送的請(qǐng)求,那么響應(yīng)就分配給誰...
?
2.Volley簡單介紹...
? 這里只是先簡單的說一下Volley,Volley框架是由Google發(fā)布的一款開源框架...這個(gè)框架主要是針對(duì)網(wǎng)絡(luò)請(qǐng)求而包裝生成的開源框架...主要功能是異步的網(wǎng)絡(luò)請(qǐng)求和圖片的加載,適用于Android這種請(qǐng)求頻繁而每次請(qǐng)求數(shù)據(jù)量并不是很大的這一類網(wǎng)絡(luò)請(qǐng)求...通過源碼能夠發(fā)現(xiàn)Volley有非常好的擴(kuò)展性,更多的地方采用接口的設(shè)計(jì)...所以我們都可以自己重寫內(nèi)部的一些方法...總體的設(shè)計(jì)思路也是非常的明確的...
? 客戶端如果想通過網(wǎng)絡(luò)連接來連接服務(wù)器,那么首先需要發(fā)送相關(guān)請(qǐng)求...每一個(gè)請(qǐng)求都需要被建立,那么建立請(qǐng)求的類就靠Request.java來實(shí)現(xiàn)...
?
? Request.java(源碼解析)
? 簡單的說說Request.java,這是Volley的最核心的類,Request.java不僅僅封裝了Request請(qǐng)求,還包括對(duì)服務(wù)器返回的Response的數(shù)據(jù)信息進(jìn)行相應(yīng)的處理..總之Request.java是一個(gè)最大的父類,內(nèi)部封裝了非常多的方法...其他的幾個(gè)子類都是通過繼承Request.java從而實(shí)現(xiàn)自己的功能...Request只是對(duì)外提供了一個(gè)接口,任何方式的請(qǐng)求只需要實(shí)現(xiàn)接口就能夠?qū)嵗约旱恼?qǐng)求對(duì)象,創(chuàng)建自己內(nèi)部的方法..從而形成一種良好的擴(kuò)展...
? 凡是繼承了Request.java必須要實(shí)現(xiàn)的一個(gè)方法...
abstract protected Response<T> parseNetworkResponse(NetworkResponse response);?? 這個(gè)方法是對(duì)網(wǎng)絡(luò)服務(wù)器響應(yīng)的一個(gè)解析過程..也是最后由這個(gè)函數(shù)通過postResponse方法,將Response傳遞給ResponseDelivery從而對(duì)響應(yīng)進(jìn)行分發(fā),不難理解,在每一個(gè)Request中實(shí)現(xiàn)這個(gè)方法,那么也就能夠知道是誰發(fā)出的請(qǐng)求,這樣在分發(fā)響應(yīng)的時(shí)候也就不會(huì)產(chǎn)生錯(cuò)誤...
??2.1 public void addMarker(String tag){}函數(shù)...
public void addMarker(String tag) {if (MarkerLog.ENABLED) {mEventLog.add(tag, Thread.currentThread().getId());} else if (mRequestBirthTime == 0) {mRequestBirthTime = SystemClock.elapsedRealtime();}}? addMarker函數(shù),其實(shí)是就是一個(gè)標(biāo)志,這個(gè)函數(shù)可以為每一個(gè)request添加相應(yīng)事件標(biāo)識(shí)符,這樣我們就可以通過捕獲標(biāo)識(shí)符的方式從而對(duì)每一個(gè)request做進(jìn)一步的操作.
? 比如說一個(gè)網(wǎng)絡(luò)請(qǐng)求從請(qǐng)求隊(duì)列取出的標(biāo)識(shí):request.addMarker("network-queue-take");
??????? 一個(gè)請(qǐng)求被取消的標(biāo)識(shí):request.addMarker("network-discard-cancelled");
? 在Volley中很容易看到這些標(biāo)識(shí),他們的存在就是為了捕獲每一個(gè)請(qǐng)求的發(fā)生狀態(tài),通過捕獲這些狀態(tài),比如說一個(gè)請(qǐng)求已經(jīng)完成,那么我們捕獲到了請(qǐng)求完成之后,我們就需要將這次請(qǐng)求從請(qǐng)求隊(duì)列當(dāng)中移除,那么這個(gè)操作的執(zhí)行就需要首先捕獲到請(qǐng)求的狀態(tài),我們才能夠采取下一步的操作...總之就是通過標(biāo)識(shí)才能夠清楚的了解請(qǐng)求到底執(zhí)行到了何種狀態(tài)...
?
? 2.2 以下幾個(gè)函數(shù)完成實(shí)體部分(Body)中驗(yàn)證參數(shù)的傳遞以及編碼過程...
? 2.2.1 public byte[] getPostBody() throws AuthFailureError{}
??????? public byte[] getBody() throws AuthFailureError{}
public byte[] getPostBody() throws AuthFailureError {// Note: For compatibility with legacy clients of volley, this implementation must remain// here instead of simply calling the getBody() function because this function must// call getPostParams() and getPostParamsEncoding() since legacy clients would have// overridden these two member functions for POST requests.Map<String, String> postParams = getPostParams();if (postParams != null && postParams.size() > 0) {return encodeParameters(postParams, getPostParamsEncoding());}return null;}public byte[] getBody() throws AuthFailureError {Map<String, String> params = getParams();if (params != null && params.size() > 0) {return encodeParameters(params, getParamsEncoding());}return null;}?? 這兩個(gè)函數(shù)想必大家看函數(shù)名稱估計(jì)都能明白到底是怎么回事了,只不過這里有個(gè)小小的區(qū)別...第一個(gè)方法僅僅是對(duì)Post請(qǐng)求方式中Body實(shí)體部分的獲取,而第二個(gè)是對(duì)Post或Put請(qǐng)求方式中Body實(shí)體部分的獲取...
? 我們知道網(wǎng)絡(luò)請(qǐng)求時(shí),信息是以數(shù)據(jù)報(bào)的形式進(jìn)行傳遞的,數(shù)據(jù)報(bào)有頭部(Headers)和實(shí)體(Body)部分...實(shí)體一般都是封裝著想要發(fā)送的數(shù)據(jù)以及驗(yàn)證信息...因此想要獲取Body中的實(shí)體數(shù)據(jù)就必須要通過某種方法來獲取原生態(tài)的實(shí)體數(shù)據(jù)(Body)...獲取了實(shí)體數(shù)據(jù)之后,就可以提交驗(yàn)證以及發(fā)送數(shù)據(jù)...那么上面兩個(gè)函數(shù)就是用來解決這個(gè)問題的...
? 我們可以從源碼看到,二者分別調(diào)用getParams()和getPostParams()函數(shù)...
? 2.2.2 protected Map<String,String> getPostParams() throws AuthFailureError{}
??????? protected Map<String,String> getParams() throws AuthFailureError{}
?
protected Map<String, String> getPostParams() throws AuthFailureError {return getParams();}protected Map<String, String> getParams() throws AuthFailureError {return null;}? 這兩個(gè)方法就是獲取數(shù)據(jù)報(bào)中Body用于驗(yàn)證或授權(quán)時(shí)傳遞的參數(shù),通過源碼我們可以看到,方法的返回值是空值,這也不難理解,如果客戶端想要完成驗(yàn)證和授權(quán),必須要由客戶端發(fā)送驗(yàn)證數(shù)據(jù),通過對(duì)客戶端驗(yàn)證數(shù)據(jù)信息的抓取,接著應(yīng)用程序重寫上面的兩個(gè)方法,客戶端的驗(yàn)證數(shù)據(jù)信息被封裝到這兩個(gè)方法內(nèi),這樣服務(wù)器就可以真正的獲取到客戶端提交的信息了..來張圖片方便大家理解...
? 這里還涉及到了一個(gè)參數(shù)的編碼...通過調(diào)用encodeParamters()方法...
? 2.2.3 private byte[] encodeParameters(Map<String,String>params,String paramsEncoding){}
? 這個(gè)方法需要對(duì)傳遞過來的所有參數(shù)進(jìn)行遍歷...將參數(shù)轉(zhuǎn)化成 postid=4868291&update=1 這樣的形式...我們?cè)谠L問網(wǎng)站的時(shí)候經(jīng)常會(huì)在url看到這樣類似的字串,那也就是傳遞的參數(shù)想必也就不難理解了...
?
private byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {StringBuilder encodedParams = new StringBuilder();try {for (Map.Entry<String, String> entry : params.entrySet()) {encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));encodedParams.append('=');encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));encodedParams.append('&');}return encodedParams.toString().getBytes(paramsEncoding);} catch (UnsupportedEncodingException uee) {throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);}}?
? 2.3 請(qǐng)求完成后需要執(zhí)行的函數(shù)...
? 2.3.1 void finish(final String tag){}
? 當(dāng)一個(gè)請(qǐng)求完成之后需要對(duì)做出一些操作,首先需要做的事情就是將請(qǐng)求隊(duì)列中的這次請(qǐng)求進(jìn)行移除操作,因?yàn)檎?qǐng)求已經(jīng)完成...這也不難理解,也就是下面源碼第一個(gè)if執(zhí)行的過程,他會(huì)再次調(diào)用RequestQueue中finish()函數(shù),來移除這次請(qǐng)求,這個(gè)源碼就先不介紹...等到后面介紹RequestQueue源碼的時(shí)候再細(xì)細(xì)說一下...我們只需要知道現(xiàn)在它的功能就行了...也是這個(gè)函數(shù)的主要部分...而下面第二個(gè)if()函數(shù),其實(shí)是為了轉(zhuǎn)儲(chǔ)這次請(qǐng)求中所有的日志文件,為了以后的調(diào)試...
void finish(final String tag) {if (mRequestQueue != null) {mRequestQueue.finish(this);}if (MarkerLog.ENABLED) {final long threadId = Thread.currentThread().getId();if (Looper.myLooper() != Looper.getMainLooper()) {// If we finish marking off of the main thread, we need to// actually do it on the main thread to ensure correct ordering.Handler mainThread = new Handler(Looper.getMainLooper());mainThread.post(new Runnable() {@Overridepublic void run() {mEventLog.add(tag, threadId);mEventLog.finish(this.toString());}});return;}mEventLog.add(tag, threadId);mEventLog.finish(this.toString());} else {long requestTime = SystemClock.elapsedRealtime() - mRequestBirthTime;if (requestTime >= SLOW_REQUEST_THRESHOLD_MS) {VolleyLog.d("%d ms: %s", requestTime, this.toString());}}}?
? 2.4 Request的構(gòu)造函數(shù)...
? 2.4.1 public Request(String url,Response.ErrorListener listener){}
??????? public Request(int method,String url,Response.ErrorListener listener){}
? 構(gòu)造函數(shù)分為兩種,一個(gè)是直接通過url來執(zhí)行請(qǐng)求,一個(gè)是通過指定提交方式,然后通過url來執(zhí)行請(qǐng)求...
public Request(String url, Response.ErrorListener listener) {this(Method.DEPRECATED_GET_OR_POST, url, listener);}public Request(int method, String url, Response.ErrorListener listener) {mMethod = method;mUrl = url;mErrorListener = listener;setRetryPolicy(new DefaultRetryPolicy());mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode();}? Request只是一個(gè)抽象接口,為外部暴露接口,從而讓其他的類去實(shí)現(xiàn),其中還有許多的方法,包括請(qǐng)求失敗時(shí)的重試策略,以及請(qǐng)求緩存的一些定義...還有許多變量和方法,只是在Request中進(jìn)行了封裝,而真正去調(diào)用和實(shí)現(xiàn)這些方法則需要其他的類進(jìn)行擴(kuò)展...因此Request的源碼只是做一些簡單的介紹..介紹的也是其中非常重要的方法...其他的內(nèi)容則在后續(xù)進(jìn)行介紹...
?
?
?????
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/RGogoing/p/4868291.html
總結(jié)
以上是生活随笔為你收集整理的Android 学习笔记之Volley开源框架解析(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转:C#使用Log4Net记录日志
- 下一篇: AndroidUI的组成部分RoomBu