教你寫Android網絡框架之Request、Response類與請求隊列

教你寫Android網絡框架之Request、Response類與請求隊列

前言

教你寫Android網絡框架之基本架構一文中我們已經介紹了SimpleNet網絡框架的基本結構,今天我們就開始從代碼的角度來開始切入該網絡框架的實現,在剖析的同時我們會分析設計思路,以及爲什麼要這樣做,這樣做的好處是什麼。這樣我們不僅學到了如何實現網絡框架,也會學到設計一個通用的框架應該有哪些考慮,這就擴展到框架設計的範疇,通過這個簡單的實例希望能給新人一些幫助。當然這只是一家之言,大家都可以有自己的實現思路。

正如你所看到的,這系列博客是爲新人準備的,如果你是高手,請忽略。

在框架開發當中,很重要的一點就是抽象。也就是面向對象中重要的一條原則: 依賴倒置原則,簡單來說就是要依賴抽象,而不依賴具體。這樣就使得我們的框架具有可擴展性,同時也滿足了開閉原則,即對擴展開放,對修改關閉。針對於我們的網絡框架來說,最重要的抽象就是Reqeust類、Response類,因此今天我們就從兩個類開始切入。最後我們再引入網絡框架中的請求隊列(RequestQueue),這是SimpleNet中的中樞神經,所有的請求都需要放到該隊列,然後等待着被執行。請求隊列就像工廠中的流水線一樣,而網絡請求就像流水線上的待加工的產品。執行網絡請求的對象就類似工廠中的工人,在自己的崗位上等待流水線上傳遞過來的產品,然後對其加工,加工完就將產品放到其他的位置。它們角色對應關係參考圖1,如對SimpleNet的一些角色不太清楚可參考教你寫Android網絡框架之基本架構一文。


圖1

Request類

既然網絡框架,那麼我們先從網絡請求類開始。前文已經說過,既然是框架,那麼就需要可擴展性。因此註定了Request是抽象,而不是具體。而對於網絡請求來說,用戶得到的請求結果格式是不確定,比如有的服務器返回的是json,有的返回的是xml,有的直接是字符串。但是對於Http Response來說,它的返回數據類型都是Stream,也就是我們得到的原始數據都是二進制的流。所以在Request基類中我們必須預留方法來解析Response返回的具體類型,雖然返回的類型不同,但是他們的處理邏輯是一樣的,因此我們可把Request作爲泛型類,它的泛型類型就是它的返回數據類型,比如Request,那麼它的返回數據類型就是String類型的。另外還有請求的優先級、可取消等,我們這裏先給出核心代碼,然後再繼續分析。

上述代碼Request爲抽象類,T則爲該請求Response的數據格式。這個T是請求類中的一個比較重要的點,不同的人有不同的需求,即請求Reponse的數據格式並不是都是一樣的,我們必須考慮到請求返回類型的多樣性,用泛型T來表示返回的數據格式類型,然後Request子類覆寫對應的方法實現解析Response的數據格式,最後調用請求Listener將請求結果執行在UI線程,這樣整個請求就完成了。

每個Request都有一個序列號,該序列號由請求隊列生成,標識該請求在隊列中的序號,該序號和請求優先級決定了該請求在隊列中的排序,即它在請求隊列的執行順序。每個請求有請求方式,例如”POST”、”GET”,這裏我們用枚舉來代替,具名類型比單純的字符串更易於使用。每個Request都可以添加Header、Body參數 ( 關於請求參數的格式可以參考 四種常見的 POST 提交數據方式),並且可以取消。抽象類封裝了通用的代碼,只有可變的部分是抽象函數,這裏只有parseResponse這個函數。
例如,我們返回的數據格式是Json,那麼我們構建一個子類叫做JsonRequest,示例代碼如下。

可以看到,實現一個請求類還是非常簡單的,只需要覆寫parseResponse函數來解析你的請求返回的數據即可。這樣就保證了可擴展性,比如後面如果我想使用這個框架來做一個ImageLoader,那麼我可以創建一個ImageRequest,該請求返回的類型就是Bitmap,那麼我們只需要覆寫parseResponse函數,然後把結果轉換成Bitmap即可。

這裏引入了Response類,這個Response類存儲了請求的狀態碼、請求結果等內容,我們繼續往下看。

Response類

每個請求都對應一個Response,但這裏的問題是這個Response的數據格式我們是不知道的。我們寫的是框架,不是應用。框架只是構建一個基本環境,並且附帶一些比較常用的類,比如這裏的JsonRequest。但是重要的一點是可以讓用戶自由、簡單的擴展以實現他的需求。對於Response類來說,我們最重要的一點就是要確定請求結果的數據格式類型。我們都知道,HTTP實際上是基於TCP協議,而TCP協議又是基於Socket,Socket實際上操作的也就是輸入、輸出流,輸出流是向服務器寫數據,輸入流自然是從服務器讀取數據。因此我們在Response類中應該使用InputStream存儲結果或者使用更爲易於使用的字節數組,這裏我們使用字節數組來存儲。我們來看Response類。

這個類很簡單,只是繼承了BasicHttpResponse,然後將輸入流轉換成字節數組,然後包裝了幾個常用的方法,主要是爲了使用簡單吧。我們將結果存儲爲字節數組,這樣可以用戶可以很方便的將結果轉換爲String、bitmap等數據類型,如果直接存儲的是InputStream,那麼在很多時候用戶需要在外圍將InputStream先轉換爲字節數組,然後再轉換爲最終的格式,例如InputStream轉爲String類型。這也是爲什麼我們這裏選用byte[]而不用InputStream的原因。

請求隊列

這裏引入了一個HttpStack,這是一個接口,只有一個函數。該接口定義了執行網絡請求的抽象,代碼如下:

沒錯就是仿照Volley實現的教學簡化版,今天就先到這裏吧。關於HttpStack、NetworkExecutor、ResponseDelivery的介紹將在下一篇博客中更新,敬請期待。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章