大家知道android對ui線程的反應時間要求很高,超過5秒鐘直接anr掉,根本不給你機會多等。
而android應用與後端系統的互動是最基本的需求之一,如何實作高效的asynchronous httpclient,確定ui線程在啟動任務後交由後端異步處理與伺服器端的通信,尤為關鍵。
google過幾個方案,要麼太複雜要麼不符合要求,基本都淘汰了,最後發現這一版本的實作不錯,就拿來用了。
連結:android asynchronous httpclient tutorial
後來發現了幾個嚴重的問題,羅列如下:
1. 啟用單獨的線程後,簡直如脫缰的野馬,難以駕馭。
現象是:在調試的時候經常發現某個線程死掉(比如在伺服器down掉的時候,由于線程無法連接配接而挂掉)
後果是:隻能關掉模拟器,甚至還要重新開機eclipse,否者兩者通信出現問題,再也不能繼續聯機調試
2. 異常的處理非常弱,activity層難以捕捉并加以處理。
這個問題跟實作的機制有一定的關系,此實作根本就沒提供好的異常處理機制,以便捕捉、回報、處理合理的可預見性的異常,諸如:
1)unknownhostexception – 誰能確定手機的網絡連接配接一直正常,信号一直滿格?
2)httpresponseexception – 後端500的錯誤,說不定就蹦出來了
3)sockettimeoutexception – 逾時也是太正常不過了,如果人家在荒山野嶺(no 3g)擺弄超大的通信請求
4)諸如此類吧
是以改造就再說難免了。下面我貼出相關代碼(import就省了吧這裡),并加以簡單注釋說明,方面大家的了解。
首先定義asynchttpclient.java。這裡的重點是逾時的設定。另外我加了個cancelrequest,用以在切換activity後取消掉原有activity發出的所有的異步請求,因為一般情況下,切換了activity後是不能再更新那個ui了,否則會抛出異常,直接導緻應用crash掉,不過話說回來,這個cancel我發現好像不是那麼給力(any feedback?)。
然後是asynchttpsender。這裡我用了inputholder和outputholder來進行對象傳遞,簡單包裝了下:
再來看看我們的call back接口定義, asyncresponselistener.java:
以及抽象call back的實作,abstractasyncresponselistener.java:
這樣我們使用起來就非常清晰、簡單了。
下面貼個簡單的用戶端用法代碼片段:
1、這個是把伺服器端響應當stream用的,用以諸如檔案、圖檔下載下傳之類的場景:
2、這個是把伺服器端響應當json用的,用以諸如擷取基本文本資訊之類的場景: