Android Volley 是Google开发的一个网络lib,可以让你更加简单并且快速的访问网络数据。Volley库的网络请求都是异步的,你不必担心异步处理问题。
Volley的优点:
- 请求队列和请求优先级
- 请求Cache和内存管理
- 扩展性性强
- 可以取消请求
下载和编译volley.jar
- 需要安装git,ant,android sdk
clone代码:git clone https://android.googlesource.com/platform/frameworks/volley
编译jar:
android update project -p . ant jar添加volley.jar到你的项目中 不过已经有人将volley的代码放到github上了:
https://github.com/mcxiaoke/android-volley,你可以使用更加简单的方式来使用volley:Maven
format: jar
<span class="tag"><<span class="title">dependency</span>></span> <span class="tag"><<span class="title">groupId</span>></span>com.mcxiaoke.volley<span class="tag"></<span class="title">groupId</span>></span> <span class="tag"><<span class="title">artifactId</span>></span>library<span class="tag"></<span class="title">artifactId</span>></span> <span class="tag"><<span class="title">version</span>></span>1.0.6<span class="tag"></<span class="title">version</span>></span> <span class="tag"></<span class="title">dependency</span>></span>Gradle
format: jar
compile 'com.mcxiaoke.volley:library:1.0.6'Volley工作原理图
创建Volley 单例
使用volley时,必须要创建一个请求队列
RequestQueue,使用请求队列的最佳方式就是将它做成一个单例,整个app使用这么一个请求队列。<span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AppController</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>{ <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = AppController.class .getSimpleName(); <span class="keyword">private</span> RequestQueue mRequestQueue; <span class="keyword">private</span> ImageLoader mImageLoader; <span class="keyword">private</span> <span class="keyword">static</span> AppController mInstance; <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span>() { <span class="keyword">super</span>.onCreate(); mInstance = <span class="keyword">this</span>; } <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> AppController <span class="title">getInstance</span>() { <span class="keyword">return</span> mInstance; } <span class="keyword">public</span> RequestQueue <span class="title">getRequestQueue</span>() { <span class="keyword">if</span> (mRequestQueue == <span class="keyword">null</span>) { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } <span class="keyword">return</span> mRequestQueue; } <span class="keyword">public</span> ImageLoader <span class="title">getImageLoader</span>() { getRequestQueue(); <span class="keyword">if</span> (mImageLoader == <span class="keyword">null</span>) { mImageLoader = <span class="keyword">new</span> ImageLoader(<span class="keyword">this</span>.mRequestQueue, <span class="keyword">new</span> LruBitmapCache()); } <span class="keyword">return</span> <span class="keyword">this</span>.mImageLoader; } <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req, String tag) { <span class="comment">// set the default tag if tag is empty</span> req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); getRequestQueue().add(req); } <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req) { req.setTag(TAG); getRequestQueue().add(req); } <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">cancelPendingRequests</span>(Object tag) { <span class="keyword">if</span> (mRequestQueue != <span class="keyword">null</span>) { mRequestQueue.cancelAll(tag); } } }另外,你还需要一个Cache来存放请求的图片:
<span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LruBitmapCache</span> <span class="keyword">extends</span> <span class="title">LruCache</span><<span class="title">String</span>, <span class="title">Bitmap</span>> <span class="title">implement</span> <span class="title">ImageCache</span> </span>{ <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">getDefaultLruCacheSize</span>() { <span class="keyword">final</span> <span class="keyword">int</span> maxMemory = (<span class="keyword">int</span>) (Runtime.getRuntime().maxMemory() / <span class="number">1024</span>); <span class="keyword">final</span> <span class="keyword">int</span> cacheSize = maxMemory / <span class="number">8</span>; <span class="keyword">return</span> cacheSize; } <span class="keyword">public</span> <span class="title">LruBitmapCache</span>() { <span class="keyword">this</span>(getDefaultLruCacheSize()); } <span class="keyword">public</span> <span class="title">LruBitmapCache</span>(<span class="keyword">int</span> sizeInKiloBytes) { <span class="keyword">super</span>(sizeInKiloBytes); } <span class="annotation">@Override</span> <span class="keyword">protected</span> <span class="keyword">int</span> <span class="title">sizeOf</span>(String key, Bitmap value) { <span class="keyword">return</span> value.getRowBytes() * value.getHeight() / <span class="number">1024</span>; } <span class="annotation">@Override</span> <span class="keyword">public</span> Bitmap <span class="title">getBitmap</span>(String url) { <span class="keyword">return</span> get(url); } <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">putBitmap</span>(String url, Bitmap bitmap) { put(url, bitmap); } }别忘记在
AndroidManifest.xml文件中添加android.permission.INTERNET权限。创建Json请求
volley自带了
JsonObjectRequest和JsonArrayRequest分别来处理Json对象请求和Json数据请求(但是voley没有使用gson库写一个GsonRequest,发送一个request,volley直接返回一个java对象,不过我们可以自己写)。创建json object请求
发送一个请求只要这么简单,创建一个
JsonRequest对象,写好response回调接口,并把这个请求放到请求队列中就可以了。JsonArrayRequest也类似。<span class="comment">// Tag used to cancel the request</span> String tag_json_obj = <span class="string">"json_obj_req"</span>; String url = <span class="string">"http://api.androidhive.info/volley/person_object.json"</span>; JsonObjectRequest jsonObjReq = <span class="keyword">new</span> JsonObjectRequest(Method.GET,url, <span class="keyword">null</span>, <span class="keyword">new</span> Response.Listener<JSONObject>() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(JSONObject response) { Log.d(TAG, response.toString()); } }, <span class="keyword">new</span> Response.ErrorListener() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) { VolleyLog.d(TAG, <span class="string">"Error: "</span> + error.getMessage()); } }); <span class="comment">// Adding request to request queue</span> AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);创建String请求
StringRequest可以用来请求任何string类型的数据:json,xml,文本等等。<span class="comment">// Tag used to cancel the request</span> String tag_string_req = <span class="string">"string_req"</span>; String url = <span class="string">"http://api.androidhive.info/volley/string_response.html"</span>; ProgressDialog pDialog = <span class="keyword">new</span> ProgressDialog(<span class="keyword">this</span>); pDialog.setMessage(<span class="string">"Loading..."</span>); pDialog.show(); StringRequest strReq = <span class="keyword">new</span> StringRequest(Method.GET, url, <span class="keyword">new</span> Response.Listener<String>() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(String response) { Log.d(TAG, response.toString()); pDialog.hide(); } }, <span class="keyword">new</span> Response.ErrorListener() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) { VolleyLog.d(TAG, <span class="string">"Error: "</span> + error.getMessage()); pDialog.hide(); } }); <span class="comment">// Adding request to request queue</span> AppController.getInstance().addToRequestQueue(strReq, tag_string_req);创建POST请求
上面说的都是GET请求,下面来说一下POST请求,与GET请求不同的是,只要在创建请求的时候将请求类型改为POST请求,并且override
Request的getParams方法即可。<span class="comment">// Tag used to cancel the request</span> <span class="built_in">String</span> tag_json_obj <span class="subst">=</span> <span class="string">"json_obj_req"</span>; <span class="built_in">String</span> url <span class="subst">=</span> <span class="string">"http://api.androidhive.info/volley/person_object.json"</span>; ProgressDialog pDialog <span class="subst">=</span> <span class="literal">new</span> ProgressDialog(this); pDialog<span class="built_in">.</span>setMessage(<span class="string">"Loading..."</span>); pDialog<span class="built_in">.</span>show(); JsonObjectRequest jsonObjReq <span class="subst">=</span> <span class="literal">new</span> JsonObjectRequest(Method<span class="built_in">.</span>POST, url, <span class="built_in">null</span>, <span class="literal">new</span> Response<span class="built_in">.</span>Listener<span class="subst"><</span>JSONObject<span class="subst">></span>() { @Override <span class="keyword">public</span> <span class="literal">void</span> onResponse(JSONObject response) { <span class="keyword">Log</span><span class="built_in">.</span>d(<span class="built_in">TAG</span>, response<span class="built_in">.</span>toString()); pDialog<span class="built_in">.</span>hide(); } }, <span class="literal">new</span> Response<span class="built_in">.</span>ErrorListener() { @Override <span class="keyword">public</span> <span class="literal">void</span> onErrorResponse(VolleyError error) { VolleyLog<span class="built_in">.</span>d(<span class="built_in">TAG</span>, <span class="string">"Error: "</span> <span class="subst">+</span> error<span class="built_in">.</span>getMessage()); pDialog<span class="built_in">.</span>hide(); } }) { @Override <span class="keyword">protected</span> <span class="built_in">Map</span><span class="subst"><</span><span class="built_in">String</span>, <span class="built_in">String</span><span class="subst">></span> getParams() { <span class="built_in">Map</span><span class="subst"><</span><span class="built_in">String</span>, <span class="built_in">String</span><span class="subst">></span> <span class="keyword">params</span> <span class="subst">=</span> <span class="literal">new</span> HashMap<span class="subst"><</span><span class="built_in">String</span>, <span class="built_in">String</span><span class="subst">></span>(); <span class="keyword">params</span><span class="built_in">.</span>put(<span class="string">"name"</span>, <span class="string">"Androidhive"</span>); <span class="keyword">params</span><span class="built_in">.</span>put(<span class="string">"email"</span>, <span class="string">"abc@androidhive.info"</span>); <span class="keyword">params</span><span class="built_in">.</span>put(<span class="string">"password"</span>, <span class="string">"password123"</span>); <span class="keyword">return</span> <span class="keyword">params</span>; } }; <span class="comment">// Adding request to request queue</span> AppController<span class="built_in">.</span>getInstance()<span class="built_in">.</span>addToRequestQueue(jsonObjReq, tag_json_obj);添加请求头部信息
<span class="comment">// Tag used to cancel the request</span> String tag_json_obj = <span class="string">"json_obj_req"</span>; String url = <span class="string">"http://api.androidhive.info/volley/person_object.json"</span>; ProgressDialog pDialog = <span class="keyword">new</span> ProgressDialog(<span class="keyword">this</span>); pDialog.setMessage(<span class="string">"Loading..."</span>); pDialog.show(); JsonObjectRequest jsonObjReq = <span class="keyword">new</span> JsonObjectRequest(Method.POST,url, <span class="keyword">null</span>,<span class="keyword">new</span> Response.Listener<JSONObject>() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(JSONObject response) { Log.d(TAG, response.toString()); pDialog.hide(); } }, <span class="keyword">new</span> Response.ErrorListener() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) { VolleyLog.d(TAG, <span class="string">"Error: "</span> + error.getMessage()); pDialog.hide(); } }) { <span class="javadoc">/** * Passing some request headers * */</span> <span class="annotation">@Override</span> <span class="keyword">public</span> Map<String, String> <span class="title">getHeaders</span>() <span class="keyword">throws</span> AuthFailureError { HashMap<String, String> headers = <span class="keyword">new</span> HashMap<String, String>(); headers.put(<span class="string">"Content-Type"</span>, <span class="string">"application/json"</span>); headers.put(<span class="string">"apiKey"</span>, <span class="string">"xxxxxxxxxxxxxxx"</span>); <span class="keyword">return</span> headers; } }; <span class="comment">// Adding request to request queue</span> AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);创建Image请求
Volley库中自带了
NetworkImageView类,这个ImageView可以自动使用volley下载图片用
NetworkImageView加载图片首先,说明一下,加载图片的原理:
NetworkImageView加载图片需要一个ImageLoader和一个图片URL,这个ImageLoader对象需要一个请求队列对象和ImageCahe对象。调用NetworkImageView的setUrl方法后,首先会判断当前ImageView的URL和新传入的URL是否一致,如果相同,就不用再发送http请求了,如果不同,那么就使用ImageLoader对象来发送http请求获取图片。<span class="constant">ImageLoader imageLoader</span> = AppController.getInstance().getImageLoader(); <span class="comment">// If you are using NetworkImageView</span> imgNetWorkView.setImageUrl(Const.URL_IMAGE, imageLoader);加载一个图片只要这么简单~~~
用ImageView来加载图片
这个过程和
NetworkImageView类似ImageLoader imageLoader = AppController.getInstance().getImageLoader(); <span class="comment">// If you are using normal ImageView</span> imageLoader.get(Const.URL_IMAGE, <span class="keyword">new</span> ImageListener() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) { Log.e(TAG, <span class="string">"Image Load Error: "</span> + error.getMessage()); } <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(ImageContainer response, <span class="keyword">boolean</span> arg1) { <span class="keyword">if</span> (response.getBitmap() != <span class="keyword">null</span>) { <span class="comment">// load image into imageview</span> imageView.setImageBitmap(response.getBitmap()); } } });可以再简单一点:
// Loading image with placeholder <span class="literal">and</span> <span class="built_in">error</span> image imageLoader.get(<span class="keyword">Const</span>.URL_IMAGE, ImageLoader.getImageListener(imageView, R.drawable.ico_loading, R.drawable.ico_error));ImageLoader.getImageListener方法中已经写了一个默认的ImageListener了Volley Cache
volley中自带了强大的cache机制来管理请求cache,这会减少网络请求次数和用户等待时间。
从请求Cache中加载请求
<span class="keyword">Cache</span> <span class="keyword">cache</span> <span class="subst">=</span> AppController<span class="built_in">.</span>getInstance()<span class="built_in">.</span>getRequestQueue()<span class="built_in">.</span>getCache(); Entry entry <span class="subst">=</span> <span class="keyword">cache</span><span class="built_in">.</span>get(url); <span class="keyword">if</span>(entry <span class="subst">!=</span> <span class="built_in">null</span>){ try { <span class="built_in">String</span> <span class="built_in">data</span> <span class="subst">=</span> <span class="literal">new</span> <span class="built_in">String</span>(entry<span class="built_in">.</span><span class="built_in">data</span>, <span class="string">"UTF-8"</span>); <span class="comment">// handle data, like converting it to xml, json, bitmap etc.,</span> } catch (UnsupportedEncodingException e) { e<span class="built_in">.</span>printStackTrace(); } } }<span class="keyword">else</span>{ <span class="comment">// Cached response doesn't exists. Make network call here</span> }使请求缓存失效
失效并不意味这删除,Volley还会继续使用缓存的对象直到从服务器上获取到了新的数据,新的数据会覆盖旧的数据。
AppController.getInstance().getRequestQueue().getCache().invalidate(url, <span class="literal">true</span>);关闭Cache
如果你想将某一个请求的Cache功能关闭,直接调用
Request的setShouldCache()方法就可以:<span class="comment">// String request</span> StringRequest stringReq <span class="subst">=</span> <span class="literal">new</span> StringRequest(<span class="attribute">...</span><span class="built_in">.</span>); <span class="comment">// disable cache</span> stringReq<span class="built_in">.</span>setShouldCache(<span class="literal">false</span>);将某一URL的Cache删除
调用
Cache的remove方法可以删除这个URL的cache:AppController.getInstance().getRequestQueue().getCache().<span class="built_in">remove</span>(url);删除所有的Cache
AppController.getInstance().getRequestQueue().getCache().<span class="keyword">clear</span>();取消请求
在你添加一个请求到请求队列中的时候,你可以发现,
addToRequestQueue(request, tag)方法还接受一个tag参数,这个tag就是用来标记某一类请求的,这样就可以取消这个tag的所有请求了:<span class="built_in">String</span> tag_json_arry = <span class="string">"json_req"</span>; ApplicationController.getInstance().getRequestQueue().cancelAll(<span class="string">"feed_request"</span>);请求优先级
在创建一个request的时候可以Override
Request方法的getPriority方法返回一个优先级,优先级分为:Normal, Low, Immediate, High<span class="keyword">private</span> Priority priority = Priority.HIGH; StringRequest strReq = <span class="keyword">new</span> StringRequest(Method.GET, Const.URL_STRING_REQ, <span class="keyword">new</span> Response.Listener<String>() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span>(String response) { Log.d(TAG, response.toString()); msgResponse.setText(response.toString()); hideProgressDialog(); } }, <span class="keyword">new</span> Response.ErrorListener() { <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onErrorResponse</span>(VolleyError error) { VolleyLog.d(TAG, <span class="string">"Error: "</span> + error.getMessage()); hideProgressDialog(); } }) { <span class="annotation">@Override</span> <span class="keyword">public</span> Priority <span class="title">getPriority</span>() { <span class="keyword">return</span> priority; } };Missing! 创建xml请求 {#Missing!_创建xml请求}
就像创建Gson请求一样,你可以自定义一个
XMLRequest类来请求xml数据

💬 评论