(一).前言:
上一讲我们已经对Volley使用基础阶段涉及到字符串,json,图片等等网络数据请求相关方法的使用。今天我们对于Volley框架来一个进阶使用扩展封装,以及对上一篇遗留的问题做一下具体修改使用。主要涉及新增GsonRequest,ImageLoader列表图片加载,ImageCache,Volley框架StringRequest二次封装以及post请求新增设置请求参数方法。
FastDev4Android框架项目地址:Https://github.com/jiangqqlmj/FastDev4Android
(二).post请求扩展请求参数方法
还记得前面文章我们只是使用Request的GET请求方法,当然作为完善的网络框架POST请求必须支持,不过很可惜的是Volley框架没有给我们显示的提供设置POST请求参数的方法,不过我们有两种方法来进行设置。不过在做之前我们需要先从源码角度来分析一下。
查看源码,我们发现Volley请求最终会被封装成HttpRequest子类对象HttpUrlRequest,该方法在HttpClientStack中的createHttpRequest()方法,代码和相关注释如下:
/** * 进行创建httprequest,这边获取httprequest的子类,httpurlrequest * Creates the appropriate subclass ofHttpUriRequest for passed in request. */ @SuppressWarnings("deprecation") /* protected */ static HttpUriRequest createHttpRequest(Request<?> request, Map<String, String>additionalheaders) throws AuthFailureError { switch (request.getMethod()) { case Method.DEPRECATED_GET_OR_POST:{ // This is the deprecated waythat needs to be handled for backwards compatibility. // If the request's post bodyis null, then the assumption is that the request is // GET. Otherwise, it is assumed that the request isa POST. byte[] postBody =request.getPostBody(); if (postBody != null) { HttpPost postRequest = new HttpPost(request.getUrl()); postRequest.addHeader(HEADER_CONTENT_TYPE,request.getPostBodyContentType()); HttpEntity entity; entity = new ByteArrayEntity(postBody); postRequest.setEntity(entity); return postRequest; } else { return newHttpGet(request.getUrl()); } } case Method.GET: return newHttpGet(request.getUrl()); case Method.DELETE: return newHttpDelete(request.getUrl()); case Method.POST: { HttpPost postRequest = new HttpPost(request.getUrl()); postRequest.addHeader(HEADER_CONTENT_TYPE,request.getBodyContentType()); //设置请求体 body信息 -如果请求体不为空---[注意] setEntityIfNonEmptyBody(postRequest, request); return postRequest; } case Method.PUT: { HttpPut putRequest = new HttpPut(request.getUrl()); putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); setEntityIfNonEmptyBody(putRequest, request); return putRequest; } case Method.HEAD: return new HttpHead(request.getUrl()); case Method.OPTIONS: return new HttpOptions(request.getUrl()); case Method.TRACE: return new HttpTrace(request.getUrl()); case Method.PATCH: { HttpPatch patchRequest = newHttpPatch(request.getUrl()); patchRequest.addHeader(HEADER_CONTENT_TYPE,request.getBodyContentType()); setEntityIfNonEmptyBody(patchRequest, request); return patchRequest; } default: throw newIllegalStateException("Unknown request method."); } }
注意查看以上caseMethod.POST部分中的setEntityIfNonEmptyBody();中进行设置请求体相关数据:
/** * 如果request的请求体不为空,进行设置请求体信息 * @param httpRequest * @param request * @throws AuthFailureError */ private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest, Request<?> request) throws AuthFailureError { byte[] body = request.getBody(); if (body != null) { HttpEntity entity = new ByteArrayEntity(body); httpRequest.setEntity(entity); } }
然后会执行Request中getBody()方法来获取请求体。
/** * Returns the raw POST or PUT body to besent. * 如果请求是POST或者PUT方法,去获取请求参数信息,然后设置到请求中 * <p>By default, the body consistsof the request parameters in * application/x-www-form-urlencodedformat. When overriding this method, consider overriding * {@link #getBodyContentType()} as well tomatch the new body format. * * @throws AuthFailureError in the event ofauth failure */ public byte[] getBody() throws AuthFailureError { //获取请求参数信息 Map<String, String> params =getParams(); if (params != null &¶ms.size() > 0) { return encodeParameters(params,getParamsEncoding()); } return null; }
最后会获取XxxRequest的基类Requst类中的getParams()来获取请求参数信息,然后设置进去。
OK这个设置POST请求参数信息的流程大家应该能清楚吧。但是Volley源代码这边就直接返回null,如下:
protected Map<String, String> getParams() throws AuthFailureError { return null; }
又因为Volley是开源的,那么下面我们开源对Request和XxxRequest类进行改造修改源代码,往外提供POST请求参数设置的方法,修改步骤如下:
2.1.Request类一个Map对象mParams,然后添加set方法,然后在getParams()进行return该mParams。具体修改如下:
/** * 自定义修改 新增POST请求参数map */ protected Map<String,String> mParams=null; public void setParams(Map<String,String> params) { this.mParams = params; }
/** * 进行获取post请求参数数据 * Returns a Map of parameters to be usedfor a POST or PUT request. Can throw * {@link AuthFailureError} asauthentication may be required to provide these values. * * <p>Note that you can directlyoverride {@link #getBody()} for custom data.</p> * * @throws AuthFailureError in the event ofauth failure */ protected Map<String, String> getParams() throws AuthFailureError { //return null; //重新进行返回params return mParams; }
2.2.间接着我们对StringRequest类进行扩展一个构造方法,加入请求参数Map对象,具体代码如下:
/** * 扩展POST请求构造函数 * @param url 请求地址 * @param listener 数据请求加载成功监听器 * @param errorListener 数据请求加载失败监听器 * @param params POST请求参数 */ public StringRequest(String url,Listener<String> listener, ErrorListenererrorListener,Map<String,String> params) { this(Method.POST, url, listener,errorListener); //进行初始化Request中post 请求参数 setParams(params); }
OK这两步修改就完成了POST请求参数设置扩展,下面我们来一看一下具体使用方法:
RequestQueue requestQueue=Volley.newRequestQueue(this); //修改Volley源代码,扩展StringRequest支持post参数设置 Map<String,String>params=new HashMap<String,String>(); params.put("username","zhangsan"); params.put("password","12345"); StringRequest post_stringRequest=new StringRequest("http://10.18.3.123:8080/SalesWebTest/TestVolleyPost",new Response.Listener<String>() { @Override public void onResponse(String response) { tv_result.setVisibility(View.VISIBLE); img_result.setVisibility(View.GONE); tv_result.setText(response.toString()); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { } },params); requestQueue.add(post_stringRequest)
这样就完成POST请求参数设置的扩展,另外的一种方案是创建StringRequest对象的时候实匿名类中重写getParams()方法,然后构造Map对象设置参数信息return该对象即可。不过个人觉的这种方案不推荐还是使用设置的方法比较好。
(三).Imageloader和ImageCache
在前面使用ImageLoder对象加载图片的时候,有一个优点我们没有深入讲解,因为ImageLoader是支持缓存功能,所以我们在创建ImageLoader需要传入一个缓存管理器,里面传入我们自定义的缓存策略,Fdv_ImageCache我们这边引入LruCache算法具体实现如下:
packagecom.chinaztt.fdv; importandroid.graphics.Bitmap; importandroid.util.LruCache; importcom.android.volley.toolbox.ImageLoader; /** * 当前类注释:图片缓存器,实现ImageLoder.ImageCache实现其中的方法,具体图片怎么样缓存让我们自己来实现 * 这样可以考虑到将来的扩展性 * 项目名:FastDev4Android * 包名:com.chinaztt.fdv * 作者:江清清 on 15/11/12 12:31 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ public class Fdv_ImageCache implements ImageLoader.ImageCache { private LruCache<String, Bitmap>mCache=null; private static final intCACHE_MAX_SIZE = 8 * 1024 * 1024; //默认缓存大小为8M public Fdv_ImageCache(){ if(mCache==null){ mCache = new LruCache<String,Bitmap>(CACHE_MAX_SIZE) { @Override protected int sizeOf(Stringkey, Bitmap bitmap) { return bitmap.getRowBytes()* bitmap.getHeight(); } }; } } /** * 从缓存中获取图片 * @param url 获取图片key 当然该key可以根据实际情况 使用url进行变换修改 * @return */ @Override public Bitmap getBitmap(String url) { return mCache.get(url); } /** * 向缓存中添加图片 * @param url 缓存图片key,当然该key可以根据实际情况 使用url进行变换修改 不过规格需要和上面方法的key保持一致 * @param bitmap 需要缓存的图片 */ @Override public void putBitmap(String url, Bitmapbitmap) { mCache.put(url,bitmap); } }
有了图片缓存机制,然后我们在配合ImageLoader来进行列表上面加载异步图片的实现,具体实现方式如下:
/** * 当前类注释:使用ImageLoader来进行测试列表图片异步加载以及缓存 * 项目名:FastDev4Android * 包名:com.chinaztt.fda.test * 作者:江清清 on 15/11/12 15:19 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ @EActivity(R.layout.base_adapter_test_layout) public class VolleyLoaderActivity extends BaseActivity { @ViewById ListView lv_base_adapter; @ViewById TextView tv_title; private QuickAdapter<ModuleBean>mAdapter; private List<ModuleBean> moduleBeans; private RequestQueue requestQueue; private ImageLoader imageLoader; private ImageLoader.ImageListener listener; @Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); requestQueue=Volley.newRequestQueue(this); imageLoader=new ImageLoader(requestQueue,new Fdv_ImageCache()); } @AfterViews public void setViews(){ tv_title.setText("Loader 列表图片"); } @AfterViews public void bindLvData(){ moduleBeans=DataUtils.getAdapterData(); if(mAdapter==null) { mAdapter = new QuickAdapter<ModuleBean>(this, R.layout.lv_item_base_layout,moduleBeans){ @Override protected void convert(BaseAdapterHelper helper, ModuleBean item) { //列表底下显示进度 mAdapter.showIndeterminateProgress(true); helper.setText(R.id.text_lv_item_title, item.getModulename()) .setText(R.id.text_lv_item_description, item.getDescription()); //setImageUrl(R.id.img_lv_item, item.getImgurl()); //使用ImageLoader进行加载图片 ImageView loader_img=helper.getView(R.id.img_lv_item); listener=ImageLoader.getImageListener(loader_img,R.drawable.ic_loading,R.drawable.ic_loading); imageLoader.get(item.getImgurl(),listener); } }; lv_base_adapter.setAdapter(mAdapter); } } }
运行效果如下:
(四).GsonRequest封装
前面我们已经使用过JsonObjectRequest,JsonArrayRequest两个工具类,这边是采用Android自身提供的JSONObject和JSONArray来进行实现解析JSON数据的,不过我们也知道如果我们已经有JSONObject和JSONArray对象然后一步步的解析还是挺麻烦的,所以我们这边可以使用JSON快速解析框架Gson来进行解决这个问题。现在我们自定义一个GsonRequest来专门处理请求GSON解析。在做之前我们先要看一下StringRequest的实现,首先StringRequest是继承Request类然后实现两个抽象方法,间接着提供若干个构造方法(进行数据初始化,请求类型GET/POST…,请求服务器地址,相应成功是否回调接口)。因为StringRequest的实现代码很少而且较简单,那么我们模仿StringRequest类的实现可以写出来一下GsonRequest代码如下:
/** * 当前类注释:进行扩展GSON数据解析json数据 * 项目名:FastDev4Android * 包名:com.android.volley.toolbox * 作者:江清清 on 15/11/12 18:28 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ public class GsonRequest<T> extends Request<T> { private final Response.Listener<T>listener; private Gson gson; private Class<T> mClass; /** * GsonRequest 构造函数 * @param method 请求方法 * @param url 请求地址 * @param listener 数据请求成功回调接口 * @param errorListener 数据请求失败回调接口 * @param pClass 需要进行解析的类 */ public GsonRequest(int method,Stringurl,Response.Listener<T> listener,Response.ErrorListenererrorListener,Class<T> pClass){ super(method,url,errorListener); this.listener=listener; gson=new Gson(); mClass=pClass; } /** * GsonRequest 构造函数 默认使用GET请求方法 * @param url * @param listener * @param errorListener * @param pClass */ public GsonRequest(Stringurl,Response.Listener<T> listener,Response.ErrorListenererrorListener,Class<T> pClass){ super(Method.GET,url,errorListener); this.listener=listener; gson=new Gson(); mClass=pClass; } /** * 数据解析 * @param response Response from thenetwork 网络请求返回数据 * @return */ @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String jsonStr=new String(response.data,HttpHeaderParser.parseCharset(response.headers)); Tdata=gson.fromJson(jsonStr,mClass); returnResponse.success(data,HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingExceptione) { return Response.error(newParseError(e)); } } /** * 数据分发 * @param response The parsed responsereturned by */ @Override protected void deliverResponse(T response){ listener.onResponse(response); } }
以上实现详解:GsonRequest继承Request,同样提供两个构造函数,然后在parseNetworkResponse()方法中进行解析数据,最后通过Gson组件来封装数据成Bean对象,最终数据回调即可。具体使用方法如下:
GsonRequest<UpdateBean> gsonRequest=new GsonRequest<UpdateBean>("http://interface.zttmall.com/update/mallUpdate",new Response.Listener<UpdateBean>() { @Override public void onResponse(UpdateBean response) { tv_result.setVisibility(View.VISIBLE); img_result.setVisibility(View.GONE); tv_result.setText(response.toString()); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { } }, UpdateBean.class);
运行效果如下:
(五).Volley二次封装(StringRequest为例)
我们在使用Volley框架请求网络数据获取的时候,一般就是以下三步骤:
1.创建RequestQueue对象
2.创建XXRequest对象(XX代表String,JSON,Image等等)
3.把XXRequest对象添加到RequestQueue中即可
虽然代码量不是不多,不过也还是需要做创建队列对象和请求对象加入到队列中的操作,而创建XxxRequest对象的构造函数中的参数又比较多,所以这边想了一种方案就是在进行网络请求的时候创建和add操作放在内部然后构造函数中的参数减少。所以这边只是以StringRequest为例,简单的封装了一个Get方法请求的方法,其他的功能还有待继续添加更新。
我们已StringRequest为例二次封装了一个类Fdv_StringRequst,我们来看以下该类的使用方法代码:
newFdv_StringRequest<String>(VolleyTestActivity.this).get("http://www.baidu.com",new Fdv_CallBackListener<String>() { @Override public void onSuccessResponse(String response) { } @Override public void onErrorResponse(VolleyError error) { } });
这样即可,不在需要以前的RequestQueuerequestQueue=Volley.newRequestQueue(this);和
requestQueue.add(object)这两句代码了,直接在内部已经做了。然后如果Get请求直接调用get()方法即可,不需要显示传入请求方法。下面我们来看一下具体实现:
5.1.定义Fdv_Volley类,里边是一个单例方法,来获取RequestQueue请求队列对象.
/** * 当前类注释:全局Fdv_Volley封装类管理类 * 项目名:FastDev4Android * 包名:com.chinaztt.fdv * 作者:江清清 on 15/11/11 23:02 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ public class Fdv_Volley { private static RequestQueue instance; public static RequestQueue getInstace(Context pContext){ if(instance==null){ instance=Volley.newRequestQueue(pContext); } return instance; } }
5.2.定义XxxRequest的基类Fdv_BaseRequest,主要功能获取请求队列对象,然后定义一个addRequest()方法,让子类进行调用,添加当前请求对象到请求队列中。
/** * 当前类注释: * 项目名:FastDev4Android * 包名:com.chinaztt.fdv * 作者:江清清 on 15/11/11 22:59 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ public class Fdv_BaseRequest{ protected static RequestQueue requestQueue; private Context mContext; protected Fdv_BaseRequest(ContextpContext){ this.mContext=pContext; } /** * 请求加入到Volley Request请求队列中 * @param request */ protected void addRequest(Request request){ Fdv_Volley.getInstace(mContext).add(request); }
5.3.请求结果回调接口Fdv_CallBackListener,这边暂时只加了两个很简单的方法,后期会进行扩展
/** * 当前类注释: * 项目名:FastDev4Android * 包名:com.chinaztt.fdv * 作者:江清清 on 15/11/11 23:18 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ public interface Fdv_CallBackListener<T> { void onSuccessResponse(T response); void onErrorResponse(VolleyError error); }
5.4.最后是我们的核心类封装过后的StringRequest,Fdv_StringRequest该类继承Fdv_BaseRequest类,在该类中我们暂时只是提供一个get()方法来获取数据中,get()方法的实现还是使用原来的StringRequest进行获取数据,得到数据使用接口回调即可,实现代码如下:
/** * 当前类注释:Volley 字符串、文本数据请求封装类 * 项目名:FastDev4Android * 包名:com.chinaztt.fdv * 作者:江清清 on 15/11/11 13:43 * 邮箱:[email protected] * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ public class Fdv_StringRequest<T> extends Fdv_BaseRequest{ public Fdv_StringRequest(Context pContext){ super(pContext); } public void get(String url, finalFdv_CallBackListener<T> listener){ StringRequest stringRequest=new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(Stringresponse) { if(listener!=null){ listener.onSuccessResponse((T) response); } } }, new Response.ErrorListener() { @Override public voidonErrorResponse(VolleyError error) { if(listener!=null){ listener.onErrorResponse(error); } } }); addRequest(stringRequest); } }
OK有了以上的几步骤,我们的对于StringRequest的get方法请求简单封装就完成了,有了这样的封装我们的功能实现就会变得代码稍微少了一点,当然我们现在的封装的功能还非常的弱,后面我这边会继续更新封装功能以及重构,让整个工具类变得更加使用。具体更新代码都会FastDev4Android项目中。后期二次封装的Volley框架代码会在Github库中更新,敬请期待~
以上所有的功能测试代码如下:
@EActivity(R.layout.volley_test_layout) public class VolleyTestActivity extends BaseActivity{ private static final StringTAG=VolleyTestActivity.class.toString(); @ViewById LinearLayout top_bar_linear_back; @ViewById TextView top_bar_title,tv_result; @ViewById ImageView img_result; @ViewById Buttonbtn_string,btn_json,btn_image_request,btn_image_loader,btn_image_network,btn_string_post,btn_loader_list,btn_gson; @ViewById NetworkImageView img_result_network; private RequestQueue requestQueue; @Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); requestQueue=Volley.newRequestQueue(this); } @Click({R.id.top_bar_linear_back,R.id.btn_string,R.id.btn_json,R.id.btn_image_request,R.id.btn_image_loader,R.id.btn_image_network,R.id.btn_string_post,R.id.btn_loader_list,R.id.btn_gson}) public void backLinearClick(View view){ switch (view.getId()){ case R.id.top_bar_linear_back: this.finish(); break; case R.id.btn_string: //获取字符串 Log.d(TAG,"点击获取字符串..."); new Fdv_StringRequest<String>(VolleyTestActivity.this).get("http://www.baidu.com",new Fdv_CallBackListener<String>() { @Override public void onSuccessResponse(String response) { tv_result.setVisibility(View.VISIBLE); img_result.setVisibility(View.GONE); tv_result.setText(response.toString()); } @Override public void onErrorResponse(VolleyError error) { } }); // StringRequest stringRequest=new StringRequest(Request.Method.GET, "http://www.baidu.com",new Response.Listener<String>() { // @Override // public void onResponse(String response) { // tv_result.setVisibility(View.VISIBLE); // img_result.setVisibility(View.GONE); // tv_result.setText(response.toString()); // } // }, new Response.ErrorListener(){ // @Override // public void onErrorResponse(VolleyError error) { // // } // }); // requestQueue.add(stringRequest); break; case R.id.btn_json: //获取json Log.d(TAG,"点击获取json..."); JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(Request.Method.GET , "http://interface.zttmall.com/update/mallUpdate",null,new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Gson gson=new Gson(); tv_result.setVisibility(View.VISIBLE); img_result.setVisibility(View.GONE); tv_result.setText(gson.fromJson(response.toString(),UpdateBean.class).toString()); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { } }); requestQueue.add(jsonObjectRequest); break; case R.id.btn_image_request: //获取图片 //http:\/\/interface.zttmall.com\/Images\/upload\/image\/20150325\/20150325083110_0898.jpg Log.d(TAG,"点击获取图片..."); ImageRequest imageRequest=new ImageRequest("http://interface.zttmall.com/Images/upload/image/20150325/20150325083110_0898.jpg" , newResponse.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { tv_result.setVisibility(View.GONE); img_result.setVisibility(View.VISIBLE); img_result.setImageBitmap(response); } }, 0, 0,ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, newResponse.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); requestQueue.add(imageRequest); break; case R.id.btn_image_loader: //使用imageloader进行获取图片 ImageLoader imageLoader=new ImageLoader(requestQueue, new Fdv_ImageCache()); tv_result.setVisibility(View.GONE); img_result.setVisibility(View.VISIBLE); ImageLoader.ImageListener listener=ImageLoader.getImageListener(img_result,R.drawable.ic_loading,R.drawable.ic_loading); imageLoader.get("http://interface.zttmall.com//Images//upload//image//20150328//20150328105404_2392.jpg",listener); break; case R.id.btn_image_network: //采用NetworkImageView imageview控件 ImageLoader network_imageLoader=new ImageLoader(requestQueue, new Fdv_ImageCache()); img_result_network.setVisibility(View.VISIBLE); img_result_network.setImageUrl("http://interface.zttmall.com//Images//upload//image//20150325//20150325083214_8280.jpg",network_imageLoader); break; case R.id.btn_string_post: //修改Volley源代码,扩展StringRequest支持post参数设置 Map<String,String>params=new HashMap<String,String>(); params.put("username","zhangsan"); params.put("password","12345"); StringRequestpost_stringRequest=new StringRequest("http://10.18.3.123:8080/SalesWebTest/TestVolleyPost",new Response.Listener<String>() { @Override public void onResponse(String response) { tv_result.setVisibility(View.VISIBLE); img_result.setVisibility(View.GONE); tv_result.setText(response.toString()); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { } },params); requestQueue.add(post_stringRequest); break; case R.id.btn_loader_list: //进行使用ImageLoader加载图片列表 openActivity(VolleyLoaderActivity_.class); break; case R.id.btn_gson: //使用扩展工具 GsonRequest进行请求 GsonRequest<UpdateBean> gsonRequest=new GsonRequest<UpdateBean>("http://interface.zttmall.com/update/mallUpdate",new Response.Listener<UpdateBean>() { @Override public void onResponse(UpdateBean response) { tv_result.setVisibility(View.VISIBLE); img_result.setVisibility(View.GONE); tv_result.setText(response.toString()); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { } }, UpdateBean.class); requestQueue.add(gsonRequest); break; } } @AfterViews public void setViews(){ top_bar_title.setText("Volley网络框架测试实例"); } }
整个功能测试功能点如下图:
(六).结束语:
到此为止我们已经讲完了Volley框架进阶部分:POST请求参数修改,图片缓存器,使用最佳实践,二次封装等相关高级进阶。具体实例和框架注释过的全部代码已经上传到FastDev4Android项目中了。同时欢迎大家去Github站点进行clone或者下载浏览:
https://github.com/jiangqqlmj/FastDev4Android 同时欢迎大家star和fork整个开源快速开发框架项目~
最后对于Volley框架二次封装的代码库,我这边会继续进行更新,后面会放入单独的Git库中,库地址后面会放出来的,敬请期待~