林育曼+溫子儀+鄧圳立+羅枳珊+劉茹+饒浩
摘要:為簡化安卓下HTTP連接請求的操作,在HttpURLConnection連接的基礎上,封裝連接與異步到一個aar上,最終用一至二行代碼實現(xiàn)想要的操作,提高工作效率。在減少操作代碼的同時,也保留了異步操作的靈活性。
關鍵詞:安卓;SDK;連接aar;異步;HTTP連接
中圖分類號:TP311 文獻標識碼:A 文章編號:1009-3044(2018)01-0053-02
Abstract: To simplify the operation of the HTTP connection request under Android, Based on the HttpURLConnection, connection was encapsulated and asynchronous to AAR. One or two lines of code were used to implement the desired operation. The efficiency of software development has been improved. The flexibility of asynchronous operations was also retained.
Key words: android; SDK; connection aar; asynchronous; http connection
1 背景
隨著智能手機的普及,安卓設備的應用層出不窮,手機應用聯(lián)網(wǎng)獲取數(shù)據(jù)是必不可少的。傳統(tǒng)的安卓開發(fā)使用鍵值對傳值,或者利用json 解析,但是往往諸如此類重復的代碼需要在很多地方出現(xiàn),影響整體代碼質(zhì)量。另一方面,代碼多了也容易出錯,往往一個空指針就需要一番調(diào)試。面向?qū)ο蟪绦蛟O計很好地解決了這個問題,把很多復雜繁瑣的操作封裝起來,供用戶調(diào)用。用戶只要會使用方法操作就行,無須花費精力去研究。因此,善于利用封裝好所需類的包,可以為開發(fā)帶來便利。
2 Android連接協(xié)議和解析方式
Android使用java語言進行開發(fā),java里面連接的API有HttpURLConnection和 HttpClient,目前官方已經(jīng)不推薦使用HttpClient,并且HttpURLConnection在原則上也會比HttpClient要快。故而Android常使用HttpURLConnection連接。
每個HttpURLConnection實例都可用于生成單個請求,但是其他實例可以透明地共享連接到HTTP服務器的基礎網(wǎng)絡。請求后在 HttpURLConnection的InputStream或OutputStream上調(diào)用close()方法可以釋放與此實例關聯(lián)的網(wǎng)絡資源,對共享的持久連接沒有任何影響。如果在調(diào)用 disconnect() 時持久連接空閑,則可能關閉基礎套接字。
HttpURLConnection已經(jīng)封裝好URL.openConnection()打開一個連接強制轉(zhuǎn)換為HttpURLConnection。然后為其設置“POST”或“GET”以及連接超時時間。若HttpURLConnection的返回碼為200則表示連接成功。可以進行下一步操作。
數(shù)據(jù)請求有POST和GET兩種,服務器根據(jù)請求的不同給予不同的處理。對于服務器傳過來的數(shù)據(jù)需要根據(jù)數(shù)據(jù)的格式進行解析,較為常用的是JSON和XML,移動開發(fā),用的比較多的是JSON。而傳遞參數(shù)則是直接編輯傳遞過程的參數(shù),如“www.xxx.com/login?phone=110&user=dxs”。
3 常規(guī)連接方式
常規(guī)開發(fā)采用異步開發(fā),比如一個登錄的接口,需要POST傳遞手機號和密碼參數(shù)到服務器,服務器再傳遞登錄信息回來。
首先建一個服務器模擬登錄的接口,這個接口接收兩個參數(shù),一個手機號碼,一個加密過的密碼,接收到參數(shù)后會進行驗證,若驗證通過則返回登錄成功的狀態(tài)碼還有登錄的手機號碼;若驗證不通過,返回錯誤狀態(tài)碼還有錯誤信息。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String phone = request.getParameter("phone");
String password = request.getParameter("password");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
if(phone.equals("110")){
out.print("{status:1,data:110,message:''}");}
else{
out.print("{status:0,data:'',message:fail}");}}
手機端初始化鍵值對params, 然后把手機號和加密過的密碼分別添加到params里面,用HttpURLConnection連接把params轉(zhuǎn)為html代碼通過UTF-8編碼發(fā)給服務器。
這時候因為UI直接在UI線程操作會造成UI堵塞,這在安卓開發(fā)里是不允許出現(xiàn)的,所以可建立一個新的線程進行操作,將返回的數(shù)據(jù)傳遞給Handler句柄,在Handler進行想要的處理。endprint
4 SDK設計
4.1 4個請求類的設計
首先設計了4個請求類TextRequest、ImageRequest、FileRequest、MapRequest,具體如下:
TextRequest:有兩個靜態(tài)方法getTxt(String urlPath, String encoding),sendTxt(String urlPath, String txt, String encoding),分別從服務器獲取文本還有向服務器發(fā)送文本,用于直接發(fā)送數(shù)據(jù)或者json,xml格式數(shù)據(jù)。
ImageRequest:只提供一個基本的獲取圖片的靜態(tài)方法Bitmap getUrlImage(String url)。
FileRequest:提供三個文件上傳的靜態(tài)方法,分別通過文件名字+文件路徑,還有不帶參數(shù)的文件與帶參數(shù)的文件。
MapRequest:向服務器發(fā)送參數(shù)的類,有兩個靜態(tài)方法sendPost(String urlPath,Map
4.2 設計NetTool類調(diào)用4個請求類的方法
這里是把幾個方法整合到一個類里方便調(diào)用,并做了一些優(yōu)化處理。如GetTxt方法:
public boolean getTxt(final String urlPath, final String encoding, final int what, final Handler handler) {
(new Thread(new Runnable() {
public void run() {
try {
String result = TextRequest.getTxt(urlPath, encoding);
Message msg = new Message();
msg.what = what;
msg.obj = result;
handler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();}}
})).start();
return true;}
除了TextRequest.getTxt(urlPath, encoding)本來需要的兩個參數(shù)外,還需要傳遞Message.what和Handler,urlPath, encoding改為終態(tài)參數(shù)。將TextRequest.getTxt(urlPath, encoding)返回值即服務器返回數(shù)據(jù)作為Message的obj字段,參數(shù)what做為Message的what字段,向Handler發(fā)送Message信息。
4.3 用數(shù)組形式給出鍵值對
如果數(shù)據(jù)本來就是Map
4.4 生成aar包
新建一個android library,放入文件,重新編譯,會自動生成aar包,導入項目如圖1所示。
5 遇到的問題和解決方案
最大的問題是返回的數(shù)據(jù)要怎么返回給主程序。因為操作畢竟是在另外一個線程,要怎么從函數(shù)里面返回給主程序。一開始的思路是新建個handler,然后在Thread里調(diào)用,但是不管怎么創(chuàng)建,始終不是主程序的,無法進行溝通。后來在NetTool類建立一個result靜態(tài)字段,線程結(jié)束后返回值給result,然后把result作為函數(shù)的返回值。但是這也是不行的,無法確定線程結(jié)束的時間,自然也不知道result里面的值是不是想要的數(shù)據(jù)。之前用過較好的Imageloader軟件包能幫忙加載圖片,也是一行代碼實現(xiàn),但是因為傳遞了Context和具體的控件,內(nèi)容也較為明確,故軟件包可以代替實現(xiàn)操作。但是本軟件包并不僅為某一單一功能服務,而是希望程序員可以利用它進一步去做自己的各種操作,所以本方法不適用。最后的方法是在函數(shù)參數(shù)里傳遞handler ,而為了編碼人員更加靈活操作,把 Message.what也做為參數(shù)傳過來。這樣可以較大提高代碼效率,同時保證了數(shù)據(jù)的穩(wěn)定性。
6 結(jié)束語
常規(guī)的安卓把操作封裝成一個類,其中每次操作都要使用HttpUrlConnection連接是比較繁瑣的步驟,每次連接都要新開一個線程。為了減少代碼負擔,往往會將連接的過程分離出來,提取成一個方法,但是仍然要手動開啟一個線程。
本包將線程一并封裝,并且使用兩個數(shù)組分別傳遞參數(shù)名和參數(shù)值,無須用戶考慮線程等問題,且在已有Handler情況下一行代碼即可實現(xiàn)全部操作。線程和Handler由編碼人員自己編寫,可以靈活進行各種處理。本軟件包幫忙建立了線程,但是Handler還是程序員自己給的,what參數(shù)也由程序員給出,因此保留了靈活性。
參考文獻:
[1] 鐘鍵. 試析Android異步通信機制[J]. 電腦編程技巧與維護, 2016(10):46-47.
[2] 程藝. android studio生成aar包并在其他工程引用aar包[EB/OL]. (2017-08-20).http://blog.csdn.net/getchance/article/details/47257389.
[3] 郭霖. 第一行代碼Android[M]. 北京: 人民郵電出版社, 2014.
[4] 夏盛新. 基于Android的移動開放平臺SDK的設計與實現(xiàn)[D]. 西安: 西安電子科技大學, 2014.
[5] 薛海龍, 陳渝, 雷蕾, 等. Android應用異步編程模型性能分析[J]. 計算機科學與探索, 2017.
[6] 章蓬陽, 邵帥. Android異步框架的研究與設計[J]. 軟件, 2016, 37(2):150-154.