Volley框架的二次封裝
我們平時開發Android app 不可避免的會使用到網絡技術,大多數情況下我們都會以http或者https來請求網絡數據,而傳統的HttpURLConnection、HttpClient,使用起來稍顯繁瑣。一些網絡開發框架也應運而生,今天所要講的Volley就是其中的一種。個人比較傾向于這個網絡框架,究其原因在于他的靈活性。你可以根據你app的架構,對volley進行相應的二次封裝,使用起來相當的靈活方便。
在封裝之前我們還是來簡單了解一下volley, 先貼一個volley的下載地址,volley jar 下載地址
2013年Google I/O大會上推出了一個新的網絡通信框架——Volley。Volley可是說是把AsyncHttpClient和Universal-Image-Loader的優點集于了一身,既可以像AsyncHttpClient一樣非常簡單地進行HTTP通信,也可以像Universal-Image-Loader一樣輕松加載網絡上的圖片。除了簡單易用之外,Volley在性能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網絡操作,而對于大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。至于Volley的使用,比較簡單,不會的同學可以在網上搜搜demo,分分鐘就能上手。
鑒于目前大多數網絡請求數據格式都是Json ,我們今天就以JsonRequest來講解一下Volley的二次封裝。
第一步:使用Volley之前需要初始化 這步操作建議在Application類中實現
VolleyQueueController.init(getApplicationContext());第二步:創建訪問數據的回調接口
public interface UIDataListener<T> {
void onDataChanged(T data);
void onErrorHappend(String errorMsg);
} 第三步:請求對象的封裝 import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.json.JSONObject;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
/**
* @author Mr.Himan
*
*/
public class NetWorkRequest extends JsonRequest<JSONObject> {
private static final int TIME_OUT = 10000;
public NetWorkRequest(int method, String url,
Map<String, String> postParams, Listener<JSONObject> listener,
ErrorListener errorListener) {
super(method, url, paramstoString(postParams), listener, errorListener);
setRetryPolicy(new DefaultRetryPolicy(TIME_OUT, 0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
public NetWorkRequest(String url, List<NameValuePair> params,
Listener<JSONObject> listener, ErrorListener errorListener) {
this(Method.GET, urlBuilder(url, params), null, listener, errorListener);
}
public NetWorkRequest(String url, Listener<JSONObject> listener,
ErrorListener errorListener) {
this(Method.GET, url, null, listener, errorListener);
}
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
JSONObject jsonObject = new JSONObject(new String(response.data,
"UTF-8"));
return Response.success(jsonObject,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
// 拼接get 請求參數
private static String urlBuilder(String url, List<NameValuePair> params) {
return url + "?" + URLEncodedUtils.format(params, "UTF-8");
}
// 拼接Post請求參數
private static String paramstoString(Map<String, String> params) {
if (params != null && params.size() > 0) {
String paramsEncoding = "UTF-8";
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();
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: "
+ paramsEncoding, uee);
}
}
return "";
}
} 第四步:構建網絡請求Helper import java.util.List;
import java.util.Map;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Handler;
import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.VolleyError;
import com.css.volunteer.net.volley.NetWorkRequest;
import com.css.volunteer.net.volley.UIDataListener;
import com.css.volunteer.net.volley.VolleyQueueController;
import com.css.volunteer.utils.LoadingWindow;
import com.css.volunteer.utils.MToast;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
/**
* Volley框架的二次封裝
*
* @author Mr.Himan
*
*/
public abstract class NetWorkHelper<T> implements
Response.Listener<JSONObject>, ErrorListener {
private Activity mActivity;
private boolean isShowHint = true; // is show the hint message popupWindow
public NetWorkHelper(Activity activity) {
super();
this.mActivity = activity;
}
protected Activity mGetContext() {
return mActivity;
}
/**
* 是否開啟加載數據請求的提示框
*/
public void closeShowHint() {
isShowHint = false;
}
protected NetWorkRequest getRequestForGet(String url,
List<NameValuePair> params) {
if (params == null) {
return new NetWorkRequest(url, this, this);
} else {
return new NetWorkRequest(url, params, this, this);
}
}
protected NetWorkRequest getRequestForPost(String url,
Map<String, String> params) {
return new NetWorkRequest(Method.POST, url, params, this, this);
}
public void doHttpGet(String url, List<NameValuePair> params) {
if (isShowHint) {
// 彈出正在加載數據彈框
LoadingWindow.loadingWindow(mActivity, "Loading");
}
NetWorkRequest requestForGet = getRequestForGet(url, params);
requestForGet.setTag(urlBuilder(url, params));
VolleyQueueController.getInstance().cancelAll(urlBuilder(url, params));
VolleyQueueController.getInstance().add(requestForGet);
}
/**
* get請求
*
* @param url
*/
public void doHttpGet(String url) {
doHttpGet(url, null);
}
private static String urlBuilder(String url, List<NameValuePair> params) {
if (params == null) {
return url;
}
return url + "?" + URLEncodedUtils.format(params, "UTF-8");
}
/**
* post請求
*
* @param url
*/
public void doHttpPost(String url, Map<String, String> params) {
VolleyQueueController.getInstance().add(getRequestForPost(url, params));
}
@Override
public void onErrorResponse(VolleyError error) {
if (isShowHint) {
LoadingWindow.closeWindow();
}
showErrorMsg();
disposeVolleyError(error);
}
protected abstract void disposeVolleyError(VolleyError error);
@Override
public void onResponse(JSONObject response) {
if (isShowHint) {
LoadingWindow.closeWindow();
}
if (response != null) {
disposeResponse(response);
} else {
showErrorMsg();
}
}
/**
* 數據加載錯誤提示
*/
protected void showErrorMsg() {
}
protected abstract void disposeResponse(JSONObject response);
private UIDataListener<T> dataListener;
public void setDataListener(UIDataListener<T> dataListener) {
this.dataListener = dataListener;
}
protected void notifyDataChanged(T data) {
if (dataListener != null) {
dataListener.onDataChanged(data);
}
}
protected void notifyErrorHappened() {
if (dataListener != null) {
dataListener.onErrorHappend();
}
}
}到這里Volley的二次封裝就完成了,看下使用
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import com.android.volley.VolleyError;
import com.css.volunteer.manager.DialogManager;
import com.css.volunteer.net.NetWorkHelper;
import com.css.volunteer.utils.MToast;
public abstract class UserNetHelper<User> extends NetWorkHelper<T> {
public UserNetHelper(Activity context) {
super(context);
}
@Override
protected void disposeVolleyError(VolleyError error) {
onErrorHappend(error);
}
@Override
protected void disposeResponse(JSONObject response) {
// 解析數據獲取bean
String userName = response.getString("userName");
String userSex = response.getString("userSex");
User user = new User(userName,userSex);
notifyDataChanged(user);
}
@Override
protected void showErrorMsg() {
// 統一錯誤提示信息處理
}
}
public LoginActivity extends Activity{
...代碼省略...
public void getUserInfo(){
UserNetHelper userNetHelper =new UserNetHelper(this);
userNetHelper.setDataListener(new UIDataListener<User>() {
@Override
public void onDataChanged(User data) {
// 獲取user
}
<pre name="code" class="java"> @Override
public void onErrorHappend(User data) {
// 獲取數據失敗
}});
userNetHelper.doHttpGet("url 地址");
}
}
從上面的小Demo可以看到,封裝之后,在Activity里面的代碼非常簡介,只有短短幾行代碼。判斷當前網絡狀態都可以在Helper中統一處理。想請求是否具備權限,操作是否成功,獲取手機驗證碼返回結果單一的情況下,代碼復用性是相當高的。同樣你也可以根據業務需求定制數據自己的helper,可以看到我們在Helper類中傳入的Activity對象,你完全可以把一個帶下拉的ListView封裝到Helper中,再凡是使用到列表加載的邏輯,只需改動請求url 和 數據類型的解析,像分頁加載,上拉下拉等操作都可統一處理,可以極大的節約開發時間。但這樣的缺陷也顯而易見,Helper中持有Activity對象的強引用,因為網絡請求是異步操作,當你在請求網絡的時候Activity可能已經被銷毀了,這里處理不當可能會造成內存泄漏。你也可以在封裝Helper類的時候不傳入Activity對象,像現在主流的MVP模式下,Model層和View是完全分離的,如果你使用的是基于MVP的開發模式,在創建Helper類的時候就不能傳入Activity對象了,那會造成Model層和VIew層的耦合,關于MVP模式下的Volley可以參照這篇帖子 Android中的MVP模式。你也可以加入Handler進行封裝,總而言之,Voller框架相當靈活。具體使用哪種方式,就要看你具體的業務需求了。
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!