volley的发布让网络请求也变得十分便利,但是我们通常懒得很想用一两句代码实现一个网络请求,其实你再经过封装就可以做到的。还有就是实际开发当中,我们会常常遇到很多异常情况,如网络异常、超时异常等等,那么我们如果有10个activity需要请求数据,那么在10个activity当中都去处理这些异常就变得十分麻烦,通过合理的设计其实我们能够在一个地方对异常情况进行统一处理,只有正确情况,才把数据返回给activity进行展示。这里我要介绍的就是这种方法,实际开发当中,合理的设计一些代码是很重要的,可以让你的开发变得更加简便、快捷。就像一样的食料,交给一个厨师和一个不会做饭的人,做出来的显然是不同的。
喜欢通过实际demo来阐述一个解决问题的办法。上代码
package com.kroc.net;
import java.util.Map;
import android.content.Context;
import android.os.Message;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.kroc.app.MyApp;
import com.kroc.util.NetWorkUtil;
/**
* @author 林楷鹏
* @description 网络相关工具类
* @create 2014-9-27下午5:15:43
*
*/
public class NetHelper {
private static RequestQueue requestQueue;//volley请求队列
private CommonHandler mHandler;
private Context mContext;
public NetHelper(Context context, CommonHandler mHandler) {
this.mContext = context;
this.mHandler = mHandler;
}
/**
* 获取volley请求队列
* @return
*/
public static RequestQueue getRequestQueue(){
if(requestQueue == null){
requestQueue = Volley.newRequestQueue(MyApp.getApp());
}
return requestQueue;
}
/**
* post方式请求数据
* @param url
* @param params
*/
public void postAsString(String url, final Map params){
if(!NetWorkUtil.checkNetWork(mContext)){
mHandler.createExceptionMsg(new CNoNetWorkException());
return;
}
StringRequest request = new StringRequest(Request.Method.POST, url, resListener, errorListener){
protected Map getParams() throws AuthFailureError {
return params;
};
};
getRequestQueue().add(request);
}
/**
* get方式请求数据
* @param url
*/
public void getAsString(String url){
if(!NetWorkUtil.checkNetWork(mContext)){
mHandler.createExceptionMsg(new CNoNetWorkException());
return;
}
StringRequest request = new StringRequest(Request.Method.GET, url, resListener, errorListener);
getRequestQueue().add(request);
}
/**
* 响应回调
*/
private Listener resListener = new Listener() {
@Override
public void onResponse(String response) {
Message msg = mHandler.obtainMessage();
msg.obj = response;
mHandler.handleMessage(msg);
}
};
/**
* 错误回调
*/
private ErrorListener errorListener = new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if(error instanceof TimeoutError){
mHandler.createExceptionMsg(new CTimeOutException());
}
}
};
}
结合部分注释我相信还是可以看懂的,主要解释下几个重点:
正确响应了,通过handler进行分发响应结果:
private Listener resListener = new Listener() {
@Override
public void onResponse(String response) {
Message msg = mHandler.obtainMessage();
msg.obj = response;
mHandler.handleMessage(msg);
}
};
异常情况,就传入自己写的handler的子类CommonHandler处理,下面会有介绍该类:
/**
* 错误回调
*/
private ErrorListener errorListener = new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if(error instanceof TimeoutError){
mHandler.createExceptionMsg(new CTimeOutException());
}
}
};
package com.kroc.net;
import java.util.Map;
import android.os.Handler;
import android.os.Message;
import com.kroc.test.BaseActivity;
/**
* @author 林楷鹏
* @description 网络结果处理
* @create 2014-9-28下午5:10:26
*
*/
public abstract class CommonHandler extends Handler {
protected BaseActivity mActivity;
protected ICallBack mCallBack;//结果回调
protected NetHelper mNetHelper;
public CommonHandler(BaseActivity activity) {
this.mActivity = activity;
}
public NetHelper getNetHelper(){
if(mNetHelper == null){
mNetHelper = new NetHelper(mActivity, this);
}
return mNetHelper;
}
/**
* 非通用处理,交给各个请求地方自己处理
* @param msg
*/
public abstract void handleMainMessage(Message msg);
/**
* 请求服务器(不带参数)
* @param url
* @param callBack
*/
public abstract void request(ICallBack callBack, String url);
/**
* 请求服务器(带参数)
* @param url
* @param callBack
* @param params
*/
public abstract void request(ICallBack callBack, String url, Map params);
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case NetValue.STATUS_NO_NETWORK:
case NetValue.STATUS_TIMEOUT:
case NetValue.STATUS_UNKNOWN:
showToast(msg.obj.toString());
break;
default:
handleMainMessage(msg);
break;
}
}
/**
* 处理通用异常,将异常封装成message分发出去,如超时、网络异常等
* @param exc
*/
public void createExceptionMsg(Exception exc){
Message msg = this.obtainMessage();
if(exc instanceof CNoNetWorkException){
msg.what = NetValue.STATUS_NO_NETWORK;
msg.obj = NetValue.TIP_NO_NETWORK;
}else if(exc instanceof CTimeOutException){
msg.what = NetValue.STATUS_TIMEOUT;
msg.obj = NetValue.TIP_TIMEOUT;
}else{
msg.what = NetValue.STATUS_UNKNOWN;
msg.obj = NetValue.TIP_UNKNOWN;
}
sendMessage(msg);
}
private void showToast(String content){
//TODO 自己实现个toast显示
System.out.println(content);
}
}
/**
* 处理通用异常,将异常封装成message分发出去,如超时、网络异常等
* @param exc
*/
public void createExceptionMsg(Exception exc){
Message msg = this.obtainMessage();
if(exc instanceof CNoNetWorkException){
msg.what = NetValue.STATUS_NO_NETWORK;
msg.obj = NetValue.TIP_NO_NETWORK;
}else if(exc instanceof CTimeOutException){
msg.what = NetValue.STATUS_TIMEOUT;
msg.obj = NetValue.TIP_TIMEOUT;
}else{
msg.what = NetValue.STATUS_UNKNOWN;
msg.obj = NetValue.TIP_UNKNOWN;
}
sendMessage(msg);
}
在此方法当中将异常装到message当中,然后send出去,再复写handleMessage(Message msg)进行处理,如下:
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case NetValue.STATUS_NO_NETWORK:
case NetValue.STATUS_TIMEOUT:
case NetValue.STATUS_UNKNOWN:
showToast(msg.obj.toString());
break;
default:
handleMainMessage(msg);
break;
}
}
这里就可以将通用的异常解决掉了,剩下的就是正确的结果,交给handleMainMessage(Message msg),而你可以发现,这个方法我把它定义成抽象方法,为何?就要子类自己去实现处理,这就是模板设计模式的一个好处。
package com.kroc.test;
import java.util.Map;
import android.os.Message;
import com.kroc.net.CommonHandler;
import com.kroc.net.ICallBack;
public class TestBusiness extends CommonHandler {
public TestBusiness(BaseActivity activity) {
super(activity);
}
@Override
public void handleMainMessage(Message msg) {
mCallBack.displayResult(ICallBack.SUCCESS, msg.obj.toString());
}
@Override
public void request(ICallBack callBack, String url) {
this.mCallBack = callBack;
getNetHelper().getAsString(url);
}
@Override
public void request(ICallBack callBack, String url,
Map params) {
}
}
这里为了方便测试,我用get请求,准备请求个百度网页哈哈~此类我通常叫做xx的业务处理层,由于demo简陋,就没太多东西,实际当中就在这里处理数据,解析json、存储到文件、数据库啊等等等等......
最后在activity中发起请求,拿到结果,就几行,真的。
package com.kroc.test;
import com.kroc.net.ICallBack;
import com.kroc.net.NetValue;
import android.os.Bundle;
public class TestActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//请求数据
TestBusiness business = new TestBusiness(this);
business.request(new ICallBack() {
@Override
public void displayResult(int status, Object... params) {
//处理结果
System.out.println("结果这里:"+params[0]);
}
}, NetValue.TEST_URL);
}
}
正常情况如下:
然后,试下异常,关掉手机WiFi、还有3G网络,结果如下:
好啦,大概就是这样,不好的还希望批判哈哈~别太粗鲁哦。
~~~~代码下载~~~~