转-封装网络请求库,统一处理通用异常 (基于volley网络请求库)

http://blog.csdn.net/kroclin/article/details/40540761

一、前言

volley的发布让网络请求也变得十分便利,但是我们通常懒得很想用一两句代码实现一个网络请求,其实你再经过封装就可以做到的。还有就是实际开发当中,我们会常常遇到很多异常情况,如网络异常、超时异常等等,那么我们如果有10个activity需要请求数据,那么在10个activity当中都去处理这些异常就变得十分麻烦,通过合理的设计其实我们能够在一个地方对异常情况进行统一处理,只有正确情况,才把数据返回给activity进行展示。这里我要介绍的就是这种方法,实际开发当中,合理的设计一些代码是很重要的,可以让你的开发变得更加简便、快捷。就像一样的食料,交给一个厨师和一个不会做饭的人,做出来的显然是不同的。

二、demo

喜欢通过实际demo来阐述一个解决问题的办法。上代码

1、首先是对volley进行再封装,这里只是简单的用了几个方法而已,volley还有很多强大的地方等待你去发现,我算抛砖引玉吧~~

[java] view plaincopy
 
  1. package com.kroc.net;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import android.content.Context;  
  6. import android.os.Message;  
  7.   
  8. import com.android.volley.AuthFailureError;  
  9. import com.android.volley.Request;  
  10. import com.android.volley.RequestQueue;  
  11. import com.android.volley.Response.ErrorListener;  
  12. import com.android.volley.Response.Listener;  
  13. import com.android.volley.TimeoutError;  
  14. import com.android.volley.VolleyError;  
  15. import com.android.volley.toolbox.StringRequest;  
  16. import com.android.volley.toolbox.Volley;  
  17. import com.kroc.app.MyApp;  
  18. import com.kroc.util.NetWorkUtil;  
  19.   
  20. /** 
  21.  * @author 林楷鹏 
  22.  * @description 网络相关工具类 
  23.  * @create 2014-9-27下午5:15:43 
  24.  *  
  25.  */  
  26. public class NetHelper {  
  27.       
  28.     private static RequestQueue requestQueue;//volley请求队列  
  29.       
  30.     private CommonHandler mHandler;  
  31.     private Context mContext;  
  32.       
  33.     public NetHelper(Context context, CommonHandler mHandler) {  
  34.         this.mContext = context;  
  35.         this.mHandler = mHandler;  
  36.     }  
  37.       
  38.     /** 
  39.      * 获取volley请求队列 
  40.      * @return 
  41.      */  
  42.     public static RequestQueue getRequestQueue(){  
  43.         if(requestQueue == null){  
  44.             requestQueue = Volley.newRequestQueue(MyApp.getApp());  
  45.         }  
  46.         return requestQueue;  
  47.     }  
  48.       
  49.     /** 
  50.      * post方式请求数据 
  51.      * @param url 
  52.      * @param params 
  53.      */  
  54.     public void postAsString(String url, final Map<String, String> params){  
  55.         if(!NetWorkUtil.checkNetWork(mContext)){  
  56.             mHandler.createExceptionMsg(new CNoNetWorkException());  
  57.             return;  
  58.         }  
  59.         StringRequest request = new StringRequest(Request.Method.POST, url, resListener, errorListener){  
  60.             protected Map<String,String> getParams() throws AuthFailureError {  
  61.                 return params;  
  62.             };  
  63.         };  
  64.         getRequestQueue().add(request);  
  65.     }  
  66.     /** 
  67.      * get方式请求数据 
  68.      * @param url 
  69.      */  
  70.     public void getAsString(String url){  
  71.         if(!NetWorkUtil.checkNetWork(mContext)){  
  72.             mHandler.createExceptionMsg(new CNoNetWorkException());  
  73.             return;  
  74.         }  
  75.         StringRequest request = new StringRequest(Request.Method.GET, url, resListener, errorListener);  
  76.         getRequestQueue().add(request);  
  77.     }  
  78.       
  79.     /** 
  80.      * 响应回调 
  81.      */  
  82.     private Listener<String> resListener = new Listener<String>() {  
  83.   
  84.         @Override  
  85.         public void onResponse(String response) {  
  86.             Message msg = mHandler.obtainMessage();  
  87.             msg.obj = response;  
  88.             mHandler.handleMessage(msg);  
  89.         }  
  90.     };  
  91.     /** 
  92.      * 错误回调 
  93.      */  
  94.     private ErrorListener errorListener = new ErrorListener() {  
  95.   
  96.         @Override  
  97.         public void onErrorResponse(VolleyError error) {  
  98.             if(error instanceof TimeoutError){  
  99.                 mHandler.createExceptionMsg(new CTimeOutException());  
  100.             }  
  101.         }  
  102.     };  
  103.       
  104. }  

结合部分注释我相信还是可以看懂的,主要解释下几个重点:

正确响应了,通过handler进行分发响应结果:

[java] view plaincopy
 
  1. private Listener<String> resListener = new Listener<String>() {  
  2.   
  3.         @Override  
  4.         public void onResponse(String response) {  
  5.             Message msg = mHandler.obtainMessage();  
  6.             msg.obj = response;  
  7.             mHandler.handleMessage(msg);  
  8.         }  
  9.     };  

异常情况,就传入自己写的handler的子类CommonHandler处理,下面会有介绍该类:

[java] view plaincopy
 
  1. /** 
  2.      * 错误回调 
  3.      */  
  4.     private ErrorListener errorListener = new ErrorListener() {  
  5.   
  6.         @Override  
  7.         public void onErrorResponse(VolleyError error) {  
  8.             if(error instanceof TimeoutError){  
  9.                 mHandler.createExceptionMsg(new CTimeOutException());  
  10.             }  
  11.         }  
  12.     };  



2、继承handler的CommonHandler,写成抽象类就是一种设计,设计模式当中叫做模板设计模式,如果不了解,可以看我的另外文章有介绍:《设计模式学习(一)—— 模板设计模式》。

[java] view plaincopy
 
  1. package com.kroc.net;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import android.os.Handler;  
  6. import android.os.Message;  
  7.   
  8. import com.kroc.test.BaseActivity;  
  9.   
  10. /** 
  11.  * @author 林楷鹏 
  12.  * @description 网络结果处理 
  13.  * @create 2014-9-28下午5:10:26 
  14.  *  
  15.  */  
  16. public abstract class CommonHandler extends Handler {  
  17.   
  18.     protected BaseActivity mActivity;  
  19.     protected ICallBack mCallBack;//结果回调  
  20.     protected NetHelper mNetHelper;  
  21.       
  22.     public CommonHandler(BaseActivity activity) {  
  23.         this.mActivity = activity;  
  24.     }  
  25.       
  26.     public NetHelper getNetHelper(){  
  27.         if(mNetHelper == null){  
  28.             mNetHelper = new NetHelper(mActivity, this);  
  29.         }  
  30.         return mNetHelper;  
  31.     }  
  32.     /** 
  33.      * 非通用处理,交给各个请求地方自己处理 
  34.      * @param msg 
  35.      */  
  36.     public abstract void handleMainMessage(Message msg);  
  37.     /** 
  38.      * 请求服务器(不带参数) 
  39.      * @param url 
  40.      * @param callBack 
  41.      */  
  42.     public abstract void request(ICallBack callBack, String url);  
  43.     /** 
  44.      * 请求服务器(带参数) 
  45.      * @param url 
  46.      * @param callBack 
  47.      * @param params 
  48.      */  
  49.     public abstract void request(ICallBack callBack, String url, Map<String, String> params);  
  50.       
  51.     @Override  
  52.     public void handleMessage(Message msg) {  
  53.         switch (msg.what) {  
  54.         case NetValue.STATUS_NO_NETWORK:  
  55.         case NetValue.STATUS_TIMEOUT:  
  56.         case NetValue.STATUS_UNKNOWN:  
  57.             showToast(msg.obj.toString());  
  58.             break;  
  59.         default:  
  60.             handleMainMessage(msg);  
  61.             break;  
  62.         }  
  63.     }  
  64.       
  65.     /** 
  66.      * 处理通用异常,将异常封装成message分发出去,如超时、网络异常等 
  67.      * @param exc 
  68.      */  
  69.     public void createExceptionMsg(Exception exc){  
  70.           
  71.         Message msg = this.obtainMessage();  
  72.           
  73.         if(exc instanceof CNoNetWorkException){  
  74.             msg.what = NetValue.STATUS_NO_NETWORK;  
  75.             msg.obj = NetValue.TIP_NO_NETWORK;  
  76.         }else if(exc instanceof CTimeOutException){  
  77.             msg.what = NetValue.STATUS_TIMEOUT;  
  78.             msg.obj = NetValue.TIP_TIMEOUT;  
  79.         }else{  
  80.             msg.what = NetValue.STATUS_UNKNOWN;  
  81.             msg.obj = NetValue.TIP_UNKNOWN;  
  82.         }  
  83.           
  84.         sendMessage(msg);  
  85.     }  
  86.       
  87.     private void showToast(String content){  
  88.         //TODO 自己实现个toast显示  
  89.         System.out.println(content);  
  90.     }  
  91. }  


类中主要的点就在对异常数据的处理,如下:

[java] view plaincopy
 
  1. /** 
  2.      * 处理通用异常,将异常封装成message分发出去,如超时、网络异常等 
  3.      * @param exc 
  4.      */  
  5.     public void createExceptionMsg(Exception exc){  
  6.           
  7.         Message msg = this.obtainMessage();  
  8.           
  9.         if(exc instanceof CNoNetWorkException){  
  10.             msg.what = NetValue.STATUS_NO_NETWORK;  
  11.             msg.obj = NetValue.TIP_NO_NETWORK;  
  12.         }else if(exc instanceof CTimeOutException){  
  13.             msg.what = NetValue.STATUS_TIMEOUT;  
  14.             msg.obj = NetValue.TIP_TIMEOUT;  
  15.         }else{  
  16.             msg.what = NetValue.STATUS_UNKNOWN;  
  17.             msg.obj = NetValue.TIP_UNKNOWN;  
  18.         }  
  19.           
  20.         sendMessage(msg);  
  21.     }  

在此方法当中将异常装到message当中,然后send出去,再复写handleMessage(Message msg)进行处理,如下:

[java] view plaincopy
 
  1. @Override  
  2.     public void handleMessage(Message msg) {  
  3.         switch (msg.what) {  
  4.         case NetValue.STATUS_NO_NETWORK:  
  5.         case NetValue.STATUS_TIMEOUT:  
  6.         case NetValue.STATUS_UNKNOWN:  
  7.             showToast(msg.obj.toString());  
  8.             break;  
  9.         default:  
  10.             handleMainMessage(msg);  
  11.             break;  
  12.         }  
  13.     }  

这里就可以将通用的异常解决掉了,剩下的就是正确的结果,交给handleMainMessage(Message msg),而你可以发现,这个方法我把它定义成抽象方法,为何?就要子类自己去实现处理,这就是模板设计模式的一个好处。

3、好啦,比较重点的两个类也在此。折腾了这么一会,上些测试代码看看怎样~~此类继承了刚刚的抽象类CommonHandler,实现抽象方法:

[java] view plaincopy
 
  1. package com.kroc.test;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import android.os.Message;  
  6.   
  7. import com.kroc.net.CommonHandler;  
  8. import com.kroc.net.ICallBack;  
  9.   
  10. public class TestBusiness extends CommonHandler {  
  11.       
  12.     public TestBusiness(BaseActivity activity) {  
  13.         super(activity);  
  14.     }  
  15.   
  16.     @Override  
  17.     public void handleMainMessage(Message msg) {  
  18.         mCallBack.displayResult(ICallBack.SUCCESS, msg.obj.toString());  
  19.     }  
  20.   
  21.     @Override  
  22.     public void request(ICallBack callBack, String url) {  
  23.         this.mCallBack = callBack;  
  24.         getNetHelper().getAsString(url);  
  25.     }  
  26.   
  27.     @Override  
  28.     public void request(ICallBack callBack, String url,  
  29.             Map<String, String> params) {  
  30.   
  31.     }  
  32.   
  33. }  

这里为了方便测试,我用get请求,准备请求个百度网页哈哈~此类我通常叫做xx的业务处理层,由于demo简陋,就没太多东西,实际当中就在这里处理数据,解析json、存储到文件、数据库啊等等等等......

最后在activity中发起请求,拿到结果,就几行,真的。

[java] view plaincopy
 
  1. package com.kroc.test;  
  2.   
  3. import com.kroc.net.ICallBack;  
  4. import com.kroc.net.NetValue;  
  5.   
  6. import android.os.Bundle;  
  7.   
  8. public class TestActivity extends BaseActivity {  
  9.   
  10.     @Override  
  11.     protected void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         //请求数据  
  14.         TestBusiness business = new TestBusiness(this);  
  15.         business.request(new ICallBack() {  
  16.               
  17.             @Override  
  18.             public void displayResult(int status, Object... params) {  
  19.                 //处理结果  
  20.                 System.out.println("结果这里:"+params[0]);  
  21.                   
  22.             }  
  23.         }, NetValue.TEST_URL);  
  24.     }  
  25. }  

我们看看打印结果,为了展示方便就这样简陋点啦,不要在意这些细节哈哈~~

正常情况如下:



然后,试下异常,关掉手机WiFi、还有3G网络,结果如下:

好啦,大概就是这样,不好的还希望批判哈哈~别太粗鲁哦。

~~~~代码下载~~~~

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/awkflf11/p/4609183.html