Android中volley封装实践记录

发布时间:2019-08-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Android中volley封装实践记录脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

在项目中一般使用使用volley方式如下,用起来给人一种很乱的感觉,于是一种盘它的想法油然而生。

 public void get() { String url = "https://tcc.taobao.COM/cc/json/mobile_tel_segment.htm&#63;tel=......"; StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {     @override     public void onResponse(String s) {      Toast.makeText(MainActivITy.this,s,Toast.LENGTH_SHORT).show();     }    }, new Response.ErrorListener() {     @Override     public void onErrorResponse(VolleyError volleyError) {      Toast.makeText(MainActivity.this,volleyError.toString(),Toast.LENGTH_SHORT).show();     }    });    request.setTag("abcGet");    MyApplication.getHttpQueues().add(request);   }@H_512_11@ 

首先看一下我封装后的使用例子:

  PRivate void initData() {   NewsApi.getInfo(new NetCallback<News>() {    @Override    public void OnSuccess(final News result) {     mAdapter.setData(result.getResult().getData());    }    @Override    public void OnError(RestfulError error) {    }   });  }

有没有看起来很舒服的感觉。好吧,让我开始盘它吧!

1.首先我先去写了一个基类,用来创建一个新的request并把它加入到volley内部封装的请求队列中,代码如下:

 public abstract class AuthenticatedRequestBase<T> extends Request<T> {  private final static String TAG = "AuthenticatedRequestBase";  private static final int TIME_OUT = 30000;  private static final int MAX_RETRIES = 1;  private static final float BACKOFF_MULT = 2f;  protected Context mContext;  protected RequestQueue mRequestQueue;   /**   * 创建新的请求,并把请求加入到请求队列requestQueue中   *   * @param method   * @param url   * @param cache   * @param errorListener   */  @SupPressLint("LongLOGTag")  public AuthenticatedRequestBase(int method, String url, boolean cache, Response.ErrorListener errorListener) {   suPEr(method, url, errorListener);   //this.setShouldCache(cache);   this.setRetrypolicy(new DefaultRetryPolicy(     TIME_OUT,     MAX_RETRIES,     BACKOFF_MULT));    mRequestQueue = YZ.getInstance().getRequestQueue();   if (mRequestQueue == null) {    throw new IllegalargumentException("mRequestQueue can't be null");   }    mContext = YZ.getInstance().getContext();   if (mContext == null) {    throw new IllegalargumentException("mContext can't be null");   }    //如果重新发出服务器请求的时候,需要清除之前的缓存。   if (!cache) {    Cache volleyCache = mRequestQueue.getCache();    Cache.Entry cacheEntry = volleyCache.get(url);     if (cacheEntry != null) {     volleyCache.remove(url);     Log.d(TAG, "remove volley cache:" + url);    }   }   mRequestQueue.add(this);  }   /**   * 重写这个方法,可以在http请求头里面加入token,客户端能接受的数据类型   *   * @return   * @throws AuthFailureError   */  @CallSuper  @Override  public Map<String, String> getHeaders() throws AuthFailureError {   Map<String, String> headers = new HashMap<>();   String token = "............";   //headers.put("Authorization", "bearer " + token);   //针对Get方法,申明接受的enum类型   // headers.put("Accept", "charset=utf-8");   return headers;  }   /**   * 网络错误问题统一处理   *   * @param volleyError   * @return   */  @CallSuper  @Override  protected VolleyError parseNetworkError(VolleyError volleyError) {   return super.parseNetworkError(volleyError);  } }

代码注释比较清晰,就不在赘述。

2.以get方法为例,新建一个GetRequest去继承这个基类,并出解析结果:

 public class GetRequest<TResponse> extends AuthenticatedRequestBase<TResponse> {   private final Response.Listener<TResponse> listener;  private final Class<TResponse> clazz;  private final static String TAG = "GetRequest";  private String mUrl;  private NetCallback<TResponse> cb;  private boolean cacheHit;    public GetRequest(String url, Class<TResponse> clazz, boolean cache, NetCallback<TResponse> callback) {   super(Request.Method.GET, url, cache, callback.getErrorListener());   this.listener = callback.getSuccessListener();   this.clazz = clazz;   this.mUrl = url;   this.cb = callback;    //无网络时300ms后返回callback   if (!NetUtils.isConnect(mContext) && mRequestQueue.getCache().get(url) == null) {    Handler handler = new Handler();    handler.postDelayed(new Runnable() {     @Override     public void run() {      cb.OnNetworkOff();     }    }, 300);   }  }   /**   * 这个是缓存的标记,与本地缓存相关   * @param tag   */  @Override  public void addMarker(String tag) {   super.addMarker(tag);   cacheHit = tag.equals("cache-hit");  }   @Override  protected Response<TResponse> parseNetworkResponse(NetworkResponse response) {   Gson gson = new Gson();    //无网络时,使用本地缓存,通过url去匹配缓存,volley sdk是通过url创建不同的文件来实现缓存的   if (!NetUtils.isConnect(mContext) && mRequestQueue.getCache().get(mUrl) != null) {    String JSON = new String(mRequestQueue.getCache().get(mUrl).data);    Log.d(TAG, "url==" + mUrl + ",json" + json);    cb.fResponseCacheStatus = ResponseCacheStatus.StaleFromCache;    return Response.success(gson.fromJson(json, clazz), parseCacheHeaders(response));   }    //数据是否有更新   try {    if (response.statusCode == 304) {     //服务端返回缓存数据     cb.fResponseCacheStatus = ResponseCacheStatus.NotModifieDFromServer;    } else if (response.statusCode == 200) {     if (cacheHit) {      //使用本地缓存      cb.fResponseCacheStatus = ResponseCacheStatus.FreshFromCache;     } else {      //使用服务端更新数据      cb.fResponseCacheStatus = ResponseCacheStatus.NewFromServer;     }    } else {     cb.fResponseCacheStatus = ResponseCacheStatus.NewFromServer;    }     Log.d(TAG, "fResponseCacheStatus = " + cb.fResponseCacheStatus);    String json = new String(response.data, parseCharset(response.headers));    return Response.success(gson.fromJson(json, clazz), parseCacheHeaders(response));   } catch (UnsupportedEncodingException | JsonSyntaxException e) {    return Response.error(new ParseError(e));   }  }   @Override  protected void deliverResponse(TResponse response) {   listener.onResponse(response);  }   @Override  protected VolleyError parseNetworkError(VolleyError volleyError) {   return super.parseNetworkError(volleyError);  } }

3.上面只做了返回成功的处理方式,返回失败时由NetCallback内部统一处理:

 @UiThread public abstract class NetCallback<TResponse> {  public ResponseCacheStatus fResponseCacheStatus = ResponseCacheStatus.NewFromServer;  private String TAG = this.getClass().getSimpleName();  public boolean enableAutomaticToastOnError = true;   public NetCallback() {  }   public NetCallback(boolean enableAutomaticToastOnError) {   this.enableAutomaticToastOnError = enableAutomaticToastOnError;  }   public abstract void OnSuccess(TResponse result);   public abstract void OnError(RestfulError error);   public void OnNetworkOff() {   //do nothing ,use it according to requirement  }   public Response.Listener<TResponse> getSuccessListener() {   return new Response.Listener<TResponse>() {    @Override    public void onResponse(TResponse result) {     OnSuccess(result);    }   };  }   public Response.ErrorListener getErrorListener() {   return new Response.ErrorListener() {    @Override    public void onErrorResponse(VolleyError volleyError) {     if (volleyError instanceof TimeoutError) {      Log.e(TAG, "networkResponse == null");      //volley TimeoutError      OnError(new RestfulError());     }      if (volleyError.networkResponse != null) {      int statusCode = volleyError.networkResponse.statusCode;      String errorMessage = new String(volleyError.networkResponse.data);      switch (statusCode) {       case 401:        //post a Permission authentication failed event        break;       default:        Log.d(TAG, "errorMessage =" + errorMessage);        try {         RestfulError error = new Gson().fromJson(errorMessage, RestfulError.class);         if (enableAutomaticToastOnError && error.getCode() != null) {          //toast(error.ExceptionMessage); //toast it in main thread         }         OnError(error);        } catch (Exception e) {         OnError(new RestfulError());         Log.d(TAG, "e =" + e.toString());        }        break;      }     }    }   };  } }

4.注意到没有,在AuthenticatedRequestBase内部有一个环境类YZ,主要负责获取项目主程序中的context和请求队列:

 public class YZ implements AppRequestQueue {  private static final int DEFAULT_VOLLEY_CACHE_SIZE = 100 * 1024 * 1024;  private Context context;  private int cacheSize;   private YZ() {  }   @Override  public RequestQueue getRequestQueue() {   return Volley.newRequestQueue(context, cacheSize);  }   public Context getContext() {   return context;  }   private static class SingletonHolder {   private static YZ instance = new YZ();  }   public static YZ getInstance() {   return SingletonHolder.instance;  }   /**   * need a app context   *   * @param appContext   */  public void init(final Context appContext) {   init(appContext, DEFAULT_VOLLEY_CACHE_SIZE);  }   /**   * @param appContext   * @param cacheSize   */  public void init(final Context appContext, final int cacheSize) {   this.context = appContext;   this.cacheSize = cacheSize;  } }

这个类需要在app的application中初始化:

 public class BaseApp extends Application {   public String TAG = this.getClass().getSimpleName();  public static Context applicationContext;  public static Executor threadPool;  public static final int THREAD_POOL_SIZE = 3;  public static final boolean isDebug = Buildconfig.BUILD_TYPE.equals("debug");   @Override  public void onCreate() {   super.onCreate();   applicationContext = getApplicationContext();   threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);    initNet();  }   private void initNet() {   YZ.getInstance().init(this);  }   public Context getInstance() {   return applicationContext;  }  }

4.现在可以开始外部封装啦。

 public class NewsApi {   public static void getInfo(NetCallback<News> callback) {   new GetRequest<>(inetConstant.NEWS, News.class, true, callback);  } }

还有一点,volley的缓存实现需要服务端配合在http请求的Cache-control: max-age配置支持缓存,并设定好缓存时间,否则无法生效

最后贴一张效果图:

Android中volley封装实践记录&nbsp;

图片发自简书App

到此结束,后期还会进行优化,代码在[github] (https://github.com/daydaydate/sample (本地下载))。

总结

android教程
脚本网站
android studio

脚本宝典总结

以上是脚本宝典为你收集整理的Android中volley封装实践记录全部内容,希望文章能够帮你解决Android中volley封装实践记录所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。