Volley框架的二次封装

z

      我们平时开发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 {   
  
        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 {
	
	private static final int TIME_OUT = 10000;
	
	
	public NetWorkRequest(int method, String url,
			Map postParams, Listener 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 params,
			Listener listener, ErrorListener errorListener) {
		this(Method.GET, urlBuilder(url, params), null, listener, errorListener);
	}

	
	public NetWorkRequest(String url, Listener listener,
			ErrorListener errorListener) {
		this(Method.GET, url, null, listener, errorListener);
	}

	@Override
	protected Response 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 params) {
		return url + "?" + URLEncodedUtils.format(params, "UTF-8");
	}

	// 拼接Post请求参数
	private static String paramstoString(Map params) {
		if (params != null && params.size() > 0) {
			String paramsEncoding = "UTF-8";
			StringBuilder encodedParams = new StringBuilder();
			try {
				for (Map.Entry 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 implements
		Response.Listener, 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 params) {
		if (params == null) {
			return new NetWorkRequest(url, this, this);
		} else {
			return new NetWorkRequest(url, params, this, this);
		}

	}

	protected NetWorkRequest getRequestForPost(String url,
			Map params) {
		return new NetWorkRequest(Method.POST, url, params, this, this);
	}

	public void doHttpGet(String url, List 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 params) {
		if (params == null) {
			return url;
		}
		return url + "?" + URLEncodedUtils.format(params, "UTF-8");
	}

	/**
	 * post请求
	 * 
	 * @param url
	 */
	public void doHttpPost(String url, Map 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 dataListener;

	public void setDataListener(UIDataListener 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 extends NetWorkHelper {

	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() {

                    @Override
                    public void onDataChanged(User data) {
                        // 获取user
                    }
                    
                   
                    @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框架相当灵活。具体使用哪种方式,就要看你具体的业务需求了。 
  

你可能感兴趣的:(android)