自己實現的一個簡單的HttpEngine庫
Github託管地址: https://github.com/xiebudong/HttpEngine
因為做的專案是網路視訊相關的, 所以需要把業務無關的邏輯獨立出來, 其中一大塊就是對Server的請求, 其中包括對直播點播列表的請求和對海報的請求, 在外加一些額外的和伺服器同步的請求, 總之歸結起來就只有兩種: ①請求一個字串(一般是基於json通訊) , ②請求檔案(海報或者升級apk)
接下來就可以把對網路的請求獨立出來單獨維護, 這樣不但增加了模組的複用性, 而且降低了程式碼的耦合度。
於是我把網路請求封裝成了一個library, 在專案中使用起來就方便多了。
庫的名稱叫HttpEngine, 其中核心的兩個API是:
requestString(...);
requestFile(...);
這樣業務相關的邏輯可以再對這個模組的使用進行封裝, 一層一層最終使程式碼的層次性非常清晰。
下面詳細記錄這個庫的使用 :
HttpEngine是android平臺的一個簡單的http引擎(簡單、實用),支援併發請求字串和下載檔案, 同時支援斷點續傳下載。
引擎打包為lib工程。在專案中直接以lib工程引用方式使用,也可以直接將生產的jar包放在專案的libs目錄下。
另外,專案還附帶了示例應用 - HttpEngineSample, 可以用從這個示例程式瞭解HttpEngine的使用, 也可以直接看看這個庫的使用效果怎麼樣。
HttpEngineSample的執行效果:
引擎以單例模式使用。
API使用很簡單:
HttpEngine.instance().init();
HttpEngine.instance().uninit();
HttpEngine.instance().needDebug(boolean isNeed);
HttpEngine.instance().requestString(...);
HttpEngine.instance().requestFile(...);
更詳細的API使用說明見 HttpEngine/doc/index.html
要注意幾點: init()和uninit()要成對呼叫, 而且不能漏調, 否則會引發IllegalStateException.
比如請求一個網頁:
void requestString()
{
StringRequest req = new StringRequest("http://www.baidu.com");
HttpEngine.instance().requestString(req, new StringObserver() {
@Override
public void done(StringRequest req, StringResponse resp)
{
// TODO Auto-generated method stub
Log.i(LOG_TAG, resp.getRespString());
}
});
}
再比如下載一個檔案並決定是否支援斷點續傳,(並支援下載過程中終止下載, 下次再下載同一個檔案時只要上次下載一半的檔案沒有被手動刪掉,則會從已下載的部分開始斷點續傳下載):
void downloadFile(int id, boolean isBreakpoint, String downloadUrl, String fileSavePath)
{
Log.i(LOG_TAG, "downloadFile id: " + id);
FileRequest req = null;
if (isBreakpoint)
{
req = new FileRequest(downloadUrl, fileSavePath);
req.setIsSupportBreakpointResume(true); // 顯示設定支援斷點續傳。
}
else
{
// 預設不支援斷點續傳, 無論上次有沒有下完,第二次下載時會刪除之前下載的檔案。
req = new FileRequest(downloadUrl, fileSavePath);
}
req.setId(id);
Controller controller = HttpEngine.instance().requestFile(req, new FileObserver() {
@Override
public void done(FileRequest req, FileResponse resp) {
// TODO Auto-generated method stub
// Log.i(LOG_TAG, req.toString());
// Log.i(LOG_TAG, resp.toString());
if (resp.getResponseState() != State.OK)
{
Log.w(LOG_TAG, "req " + req.getId() + " failed");
}
runOnUiThread(new UiUpdater(req.getId(), resp.getDownloadPercent()));
}
});
if (controller == null)
{
Log.w(LOG_TAG, "request failed , check your network, or filter HttpEngine log for more detail info.");
}
else
{
mControllerMap.put(id, controller); // controller儲存起來以便後面可以終止下載, 比如正在下載時
}
}
以上無論是請求字串還是請求檔案都是非同步併發執行的。 所以函式的執行都不會阻塞主執行緒, 注意如果同時發出的請求比較多的話,最好設定請求id,以便在callback中區分是哪個請求的響應。
另外, 可以通過呼叫 HttpEngine.instance().needDebug(boolean isNeed); 來決定要不要檢視引擎的log輸出, 如果打開了這個開關, 便可以在logcat過濾HttpEngine來檢視HttpEngine庫的執行log(當請求失敗時,對除錯是非常有幫助的)。
當然,如果請求失敗也可以把callback回傳的stringRequest req, StringResponse resp 或者 FileRequest req, FileResponse resp 打印出來(toString), 來檢視為什麼失敗了。