Volley 是一款很不错的网络访问请求框架,在开发过程中,使用 Volley 只需要很少的代码就可以完成对网络的请求,而且性能方面也不需要过多考虑。
实际开发过程中,Volley 确实能给我们带来很大的便利,但有时候也需要我们适当对 Volley 进行一些简单的封装,已便更好地适应我们的开发需求。
如果使用原生 Volley,我们的代码是这个样子的
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
// 请求地址
private static final String GET_SHANGXI_CITY = "http://192.168.0.100:8080/cmn-srv/apiRequest?requestCode=A10002&code=140000";
private static final String GET_TAIYUAN_DISTRICT = "http://192.168.0.100:8080/cmn-srv/apiRequest?requestCode=A10003&code=140100";
private Button btn1 = null;
private Button btn2 = null;
private RequestQueue queue;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button)findViewById(R.id.button);
btn2 = (Button)findViewById(R.id.button2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
queue = Volley.newRequestQueue(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
getShangxiAllCity();
break;
case R.id.button2:
getTaiyuanAllDistrict();
break;
default:
break;
}
}
/**
* 获取山西全部市
*/
private void getShangxiAllCity(){
// 使用Volley请求数据
JsonObjectRequest requestCity = new JsonObjectRequest(
Request.Method.GET,
GET_SHANGXI_CITY,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
Log.d("TAG",jsonObject.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Log.d("TAG",volleyError.toString());
}
}
);
queue.add(requestCity);
}
/**
* 获取太原市所有区县
*/
private void getTaiyuanAllDistrict(){
JsonObjectRequest requestDistrict = new JsonObjectRequest(
Request.Method.GET,
GET_TAIYUAN_DISTRICT,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
Log.d("TAG",jsonObject.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Log.d("TAG",volleyError.toString());
}
}
);
queue.add(requestDistrict);
}
}
服务器返回数据:
请求市返回数据
{"data":[{"id":"140100","new":false,"name":"太原市","code":"140100"},{"id":"140200","new":false,"name":"大同市","code":"140200"},{"id":"140300","new":false,"name":"阳泉市","code":"140300"},{"id":"140400","new":false,"name":"长治市","code":"140400"},{"id":"140500","new":false,"name":"晋城市","code":"140500"},{"id":"140600","new":false,"name":"朔州市","code":"140600"},{"id":"140700","new":false,"name":"晋中市","code":"140700"},{"id":"140800","new":false,"name":"运城市","code":"140800"},{"id":"140900","new":false,"name":"忻州市","code":"140900"},{"id":"141000","new":false,"name":"临汾市","code":"141000"},{"id":"141100","new":false,"name":"吕梁市","code":"141100"}],"message":"","returnCode":"1"}
请求区返回数据
{"data":[{"id":"140101","new":false,"name":"市辖区","code":"140101"},{"id":"140105","new":false,"name":"小店区","code":"140105"},{"id":"140106","new":false,"name":"迎泽区","code":"140106"},{"id":"140107","new":false,"name":"杏花岭区","code":"140107"},{"id":"140108","new":false,"name":"尖草坪区","code":"140108"},{"id":"140109","new":false,"name":"万柏林区","code":"140109"},{"id":"140110","new":false,"name":"晋源区","code":"140110"},{"id":"140121","new":false,"name":"清徐县","code":"140121"},{"id":"140122","new":false,"name":"阳曲县","code":"140122"},{"id":"140123","new":false,"name":"娄烦县","code":"140123"},{"id":"140181","new":false,"name":"古交市","code":"140181"}],"message":"","returnCode":"1"}
我们这样写肯定是没有问题的,但是如果需要有多个网络请求时,使用 Volley 原生方式进行网络请求代码就会显得很臃肿,且不利于后期维护,在参考了一些别人写的代码后,对 Volley+fastjson 进行了一次简单的封装,同样还是之前的请求,这是封装之后的代码
public class MainActivity2 extends AppCompatActivity implements View.OnClickListener,VolleyCallBack{
// 请求地址
private static final String GET_SHANGXI_CITY = "http://192.168.0.100:8080/cmn-srv/apiRequest?requestCode=A10002&code=140000";
private static final String GET_TAIYUAN_DISTRICT = "http://192.168.0.100:8080/cmn-srv/apiRequest?requestCode=A10003&code=140100";
// 请求号
private static final String GET_SHANGXI_CITY_CODE = "A10002";
private static final String GET_TAIYUAN_DISTRICT_CODE = "A10003";
private Button btnGetShangxiCity = null;
private Button btnGetTaiyuanDistrict = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGetShangxiCity = (Button)findViewById(R.id.btn_get_shangxi_city);
btnGetTaiyuanDistrict = (Button)findViewById(R.id.btn_get_taiyuan_district);
btnGetShangxiCity.setOnClickListener(this);
btnGetTaiyuanDistrict.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_get_shangxi_city:
// Volley 封装之后的请求
VolleyRequest.get(this, GET_SHANGXI_CITY_CODE, GET_SHANGXI_CITY, "正在加载",this);
break;
case R.id.btn_get_taiyuan_district:
VolleyRequest.get(this,GET_TAIYUAN_DISTRICT_CODE,GET_TAIYUAN_DISTRICT,"正在加载",this);
break;
}
}
@Override
public void requestSuccess(String requestCode, JSONObject json) {
if (null == json){
return;
}
CommonBean commonBean = JsonUtils.fromJson(json.toString(),CommonBean.class);
String returnCode = commonBean.getReturnCode();
if (returnCode.equals(JsonUtils.RETURN_OK)){
switch (requestCode){
case GET_SHANGXI_CITY_CODE:
Log.d("TAG",commonBean.getData().toString());
break;
case GET_TAIYUAN_DISTRICT_CODE:
Log.d("TAG",commonBean.getData().toString());
break;
}
}else if (returnCode.equals(JsonUtils.RETURN_ERROR)){
Toast.makeText(this, commonBean.getMessage(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void requestError(String requestCode, VolleyError e) {
switch (requestCode){
case GET_SHANGXI_CITY_CODE:
Log.d("TAG","请求市失败"+e.toString());
break;
case GET_TAIYUAN_DISTRICT_CODE:
Log.d("TAG","请求区失败"+e.toString());
break;
}
}
}
封装之后的代码可读性比之前好了很多,而且网络请求也简单了不少,还加入了网络请求进度条的支持,同一个类中如果进行不同的网络请求根据 requestCode 可以很方便地进行分类处理
下面来具体分析
VolleyRequest
发起一个网络请求
public class VolleyRequest {
/**
* 不带进度条 get 请求..
* @param tag 标签
* @param requestCode 请求码
* @param url 请求地址
* @param listener 回调接口
*/
public static void get(Object tag,String requestCode,String url,VolleyCallBack listener){
VolleyManger.get(tag, requestCode, url, listener);
}
/**
* 带 进度条 的 get 请求..
* @param tag
* @param url
* @param requestCode
* @param progressTitle 进度条提示
* @param listener
*/
public static void get(Object tag,String requestCode,String url,String progressTitle,VolleyCallBack listener){
VolleyManger.get(tag, url, requestCode, progressTitle, listener);
}
/**
* 不带 进度条的 Post 请求..
* @param tag
* @param request
* @param url
* @param jsonRequest
* @param listener
*/
public static void post(Object tag,String requestCode,String url,JSONObject jsonRequest,VolleyCallBack listener){
VolleyManger.post(tag, requestCode, url, jsonRequest, listener);
}
/**
* 带进度条的 post 请求..
* @param tag
* @param requestCode
* @param url
* @param progressTitle
* @param jsonRequest
* @param listener
*/
public static void post(Object tag,String requestCode,String url,String progressTitle,JSONObject jsonRequest,VolleyCallBack listener){
VolleyManger.post(tag, requestCode, url, progressTitle, jsonRequest, listener);
}
}
VolleyManage
对网络请求进行处理
public class VolleyManger {
// 静态,这里设计成单例模式 应该会好一点.
// 设计成单例模式..
public static RequestQueue mRequestQueue = null;
public static RequestQueue getInstance(){
if (mRequestQueue==null) {
mRequestQueue = Volley.newRequestQueue(AppContext.getContext());
}
return mRequestQueue;
}
/**
* 返回 JsonObject
*
* @param tag 上下文
* @param requestCode 请求号
* @param url url
* @param listener 监听回调..
*/
public static void get(Object tag,String requestCode,String url, VolleyCallBack listener) {
get(tag, requestCode, url, false, null, null, listener);
}
/**
* 返回JsonObject 带进度条 自定义 进度条显示的文字..
* @param tag 上下文
* @param url url
* @param requestCode 请求号
* @param progressTitle 进度条文字 ,可以为空,显示默认
* @param listener 上下文
*/
public static void get(Object tag,String url,String requestCode,String progressTitle,VolleyCallBack listener) {
LoadingFragment dialog = new LoadingFragment();
if (tag instanceof Activity) {
dialog.show(((Activity) tag).getFragmentManager(),"Loading");
}else if(tag instanceof Fragment){
// 在Fragment中 加载
dialog.show(((Fragment) tag).getFragmentManager(),"Loading");
}
dialog.setMsg(progressTitle);
get(tag, requestCode, url, true, dialog, progressTitle, listener);
}
/**
*
* @param tag 上下文
* @param requestCode 请求号
* @param url 请求地址
* @param flag 是否有进度条..
* @param p 进度条
* @param progressTitle 进度条显示内容
* @param listener 回调监听..
*/
public static void get(Object tag,String requestCode,String url,boolean flag,LoadingFragment p,String progressTitle,VolleyCallBack listener){
// 还有各种,是否有进度条之类的..
// 如果没有该怎么处理..
cancelAll(tag);
JsonObjectRequest request = new JsonObjectRequest(
Method.GET,
url,
null,
responseListener(listener, requestCode, flag, p),
responseError(listener, requestCode, flag, p));
addRequest(request, tag);
}
/**
* 不带进度条的 post 解析
* @param tag 上下文
* @param requestCode 请求码
* @param url url
* @param jsonRequest 发送的 Json 数据
* @param listener 监听回调..
*/
public static void post(Object tag,String requestCode,String url,JSONObject jsonRequest,VolleyCallBack listener){
post(tag, requestCode, url, false, null, null, jsonRequest, listener);
}
/**
* 带进度条的 post 解析
* @param tag 上下文
* @param requestCode 请求码
* @param url 地址
* @param progressTitle 进度条显示
* @param jsonRequest 发送的 Json 数据
* @param listener 回调
*/
public static void post(Object tag,String requestCode,String url,String progressTitle,JSONObject jsonRequest,VolleyCallBack listener){
LoadingFragment dialog = new LoadingFragment();
if (tag instanceof Activity) {
dialog.show(((Activity) tag).getFragmentManager(),"Loading");
}else if(tag instanceof Fragment){
// 在Fragment中 这个对话框该如何加载,这个还值得 进一步的验证..
dialog.show(((Fragment) tag).getFragmentManager(),"Loading");
}
dialog.setMsg(progressTitle);
post(tag, requestCode, url, true, dialog, progressTitle, jsonRequest, listener);
}
/**
*
* post 请求..使用 发送 Json 数据到服务器..
* @param tag 上下文
* @param requestCode 请求号
* @param url 请求地址
* @param flag 是否有进度条..
* @param p 进度条
* @param progressTitle 进度条显示内容
* @param listener 回调监听..
*/
public static void post(Object tag,String requestCode,String url,boolean flag,LoadingFragment p,String progressTitle,JSONObject jsonRequest,VolleyCallBack listener){
cancelAll(tag);
JsonObjectRequest request = new JsonObjectRequest(
Method.POST,
url,
jsonRequest,
responseListener(listener, requestCode, flag, p),
responseError(listener, requestCode, flag, p));
addRequest(request, tag);
}
/**
* 成功消息监听 返回 JSONObject
*
* @param l String 接口
* @param flag true 带进度条 flase不带进度条
* @param p 进度条的对象
* @return
*/
protected static Response.Listener<JSONObject> responseListener(
final VolleyCallBack l, final String requestCode, final boolean flag,final LoadingFragment p) {
return new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject json) {
Log.d("Log","请求号:"+requestCode+"---> "+json.toString());
l.requestSuccess(requestCode,json);
showDialog(flag, p);
}
};
}
/**
* 返回错误监听
*
* @param l String 接口
* @param flag true 带进度条 flase不带进度条
* @param p 进度条的对象
* @return
*/
protected static Response.ErrorListener responseError(
final VolleyCallBack l, final String requestCode,final boolean flag, final LoadingFragment p) {
return new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError e) {
Log.d("Log", "请求号:"+requestCode+"---> "+e.toString());
l.requestError(requestCode,e);
showDialog(flag, p);
}
};
}
private void showLoadingFragment(Context context){
LoadingFragment dialog = new LoadingFragment();
}
/**
* 判断进度条..
*
* @param flag 是否显示进度条..
* @param p
*/
private static void showDialog(final boolean flag, LoadingFragment p) {
if (flag) {
if (p.getShowsDialog()) {
p.dismiss();
}
}
}
public static void addRequest(Request<?> request, Object tag) {
if (tag != null) {
request.setTag(tag);
}
getInstance().add(request);
}
/**
* 当主页面调用协议 在结束该页面调用此方法
* @param tag
*/
public static void cancelAll(Object tag) {
getInstance().cancelAll(tag);
}
}
LoadingFrameent
该类继承 DialogFrament
,进度条显示样式
VolleyCallBack
回调接口
public interface VolleyCallBack {
/** 成功 */
public void requestSuccess(String requestCode, JSONObject json);
/** 错误 */
public void requestError(String requestCode, VolleyError e);
}
JsonUtils
和实体类 CommonBean
是根据服务器返回数据进行封装的,再具体开发过程中大家可以根据不同的需求进行封装
代码已上传,下载地址:https://github.com/zebragg/VolleyFrame2