Volley 的介绍和使用(三)
来源:互联网 发布:手机上网代理软件 编辑:程序博客网 时间:2024/05/22 04:41
这一节我们介绍自定义Request。
在上一节中我们只介绍了StringRequest
的POST的请求方式,而没有介绍JsonObjectRequest
和JsonArrayReqest
的POST请求方式,因为这两个扩展至Request
的类,覆盖了getBody()
方法,把Request
的encode 请求参数的方法修改了,把构造函数中的JSONObject对象转换成String, 直接发送出去了;所以我们要实现POST请求,需要自己实现一个Request
。
自定义Request
自己自定义一个Request
,需要继承Request
类,类似于StringRequest
中的实现。主要重写一下parseNetworkResponse()
方法,这个方法用来解析网络请求的结果。以下是 StringRequst
的源码:
public class StringRequest extends Request<String> { //用于传递请求结果的监听器 private final Listener<String> mListener; //根据给出的请求方式,创建一个新的请求 public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } //创建一个GET 请求 public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); } @Override protected void deliverResponse(String response) { mListener.onResponse(response);//传递请求结果 } //这个方法主要是将请求返回的数据进行解析等处理 @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); }}
类似我们创建一个JsonPostRequest:
public class JsonPostRequest extends Request<JSONObject> { //用于传递请求结果的监听器 public Response.Listener<JSONObject> mListener; private Map<String, String> mParames; //根据给出的请求方式,创建一个新的请求 private JsonPostRequest(@PostOnly int method, String url, Map<String, String> parames, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); this.mParames = parames; this.mListener = listener; } //创建一个POST请求 public JsonPostRequest(String url, Map<String, String> parames, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { this(POST, url, parames, listener, errorListener); } // 获取请求参数 @Override protected Map<String, String> getParams() throws AuthFailureError { return mParames; } /** * //这个方法主要是将请求返回的数据进行解析等处理 * @param response Response from the network * @return Response 对象,包含解析过的数据 */ @Override protected Response parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); //将数据封装成JSONObject return Response.success(new JSONObject(parsed), HttpHeaderParser.parseCacheHeaders(response)); } catch (JSONException e) { return Response.error(new ParseError(e)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(JSONObject response) { mListener.onResponse(response);//传递请求结果 } public static final int POST = Method.POST; /** * 创建一个注解,用来限制参数类型,这里只能传入POST这个参数 */ @IntDef({POST}) public @interface PostOnly { }}
这样我们就可以得到一个请求返回是JSONObject的请求类了。我们可以这样使用它。
private void requestByVolley(){ //1.组拼URL String mUrlStr = "http://op.juhe.cn/onebox/news/query"; //2.获取一个RequestQueue RequestQueue queue = App.getQueue(); //3.设置POST请求的参数 Map<String, String> parames = new HashMap<>(); parames.put("q", "普京");//搜索关于普京的新闻 parames.put("key", APP_KEY); //4.创建一个请求,其返回的结果以String 形式返回 JsonPostRequest requst = new JsonPostRequest(mUrlStr, parames, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { mTextView.setText(response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mTextView.setText(error.getMessage()); } }); //5.将请求添加的请求队列中,在这里请求就已经开始了 queue.add(requst);}
使用方式类似于之前的 JsonObjectRequst
的GET请求方式;类似的我么也可以做其它形式的扩展,例如可以返回 JSONArray ,可以返回某个需要的对象,当然也可以把 Gson 嵌入进去。只需要 修改一下 parseNetworkResponse()
就OK,在这里做你想要的操作。
ImageLoader
上一节介绍了 ImageRequest
,可以很简单的实现对网络图片的请求。但是这种方式是没有的缓存的,如果需要缓存就需要 ImageLoader
;它的内部实现其实也是使用ImageRequest
实现的,当然ImageLoader
比ImageRequest
更高一些,它不仅仅对图片进行了缓存还过滤了重复的链接,避免重复请求;当然使用也稍微麻烦一些。
ImageLoader
的构造方法中,需要一个RequestQueue
和一个ImageCache
。
public ImageLoader(RequestQueue queue, ImageCache imageCache) { mRequestQueue = queue; mCache = imageCache;}
所以我们需要一个 RequestQueue
和一个ImageCache
。当然如果我们还需要一个监听器,用来监听下载图片是否成功,如果成功就显示下载的图片,如果失败就显示失败图片,在下载过程中,我们不能让界面空着,也要给它一个默认图片。当然ImageLoader
提供了这样的监听器 ImageListener
。下面看看它:
ImageLoader.ImageListener listener = ImageLoader.getImageListener(mImageView, R.drawable.default_icon, R.drawable.error_icon);
上面的方法的第一个参数,是要显示图片的控件;第二个参数是默认图;第三个图片是下载失败要显示的图片。
最后我们只需要在调用 ImageLoader
的 get()
方法就OK了。
上面说的比较简单,下面我们上代码。
private void loadImageByImageLoader() { //1.图片的URL String imageURL = "http://c.hiphotos.baidu.com/image/pic/item/0dd7912397dda1449fad6f63b6b7d0a20df486be.jpg"; //2.请求队列 RequestQueue queue = App.getQueue(); //3.使用请求队列和ImageCache构造一个ImageLoader ImageLoader loader = new ImageLoader(queue, new ImageLoader.ImageCache() { @Override public Bitmap getBitmap(String url) { return null; } @Override public void putBitmap(String url, Bitmap bitmap) { } }); //4.构造一个图片下载的监听器 ImageLoader.ImageListener listener = ImageLoader.getImageListener(mImageView, R.drawable.default_icon, R.drawable.error_icon); //5.下载图片 loader.get(imageURL, listener);}
上面只是一个简单的应用,还没有用到ImageLoader
最重要的点,那就是缓存,因为上面的ImageCache
是一个空的,完全没有缓存的作用,所以我们还要写一个ImageCache
,这就用到了Android提供的LRUCahce,当然也很简单,上代码:
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) // LruCache 这个类是在Android 3.1出现的所以要加注解来标识一下public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache { public LruBitmapCache() { this(getDefaultLruCacheSize()); } //设置最大内存 public LruBitmapCache(int sizeInMib) { super(sizeInMib); } // 用来计算Bitmap的大小 @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); } @Override public Bitmap getBitmap(String url) { return get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { put(url, bitmap); } /** * 获取默认的缓存大小,为运行时堆内存的最大内存的 1/8。 * * @return 缓存大小值,以Mib为单位 */ public static int getDefaultLruCacheSize() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024 / 1024); return maxMemory / 8; }}
我们继承及成LruCache并且实现了ImageCache接口,设置了图片的缓存大小。我使用的时候可以下面这样:
ImageLoader mLoader= new ImageLoader(queue, new LruBitmapCache());
有没有感觉这样太麻烦了,每次都要写这么一大堆,当我们把ImageCache实现之后,可以把相应的代码抽取出来,做一个单例类,每次使用的时候只需要一样代码就可以实现。具体代码如下:
public class ImageLoaderManager { private RequestQueue mQueue; private ImageLoader mLoader; public static ImageLoaderManager getInstance() { return ImageLoaderManagerInstance.loaderManager; } private ImageLoaderManager() { //1.请求队列 mQueue = App.getQueue(); } private static final class ImageLoaderManagerInstance { final static ImageLoaderManager loaderManager = new ImageLoaderManager(); } public void load(ImageView view,String imageURL){ //2.使用请求队列和ImageCache构造一个ImageLoader mLoader = getImageLoader(); //3.构造一个图片下载的监听器 ImageLoader.ImageListener listener = ImageLoader.getImageListener(view, R.drawable.default_icon, R.drawable.error_icon); //4.下载图片 mLoader.get(imageURL, listener); } public ImageLoader getImageLoader() { if(mLoader == null){ mLoader= new ImageLoader(mQueue, new LruBitmapCache()); } return mLoader; }}
当我们可以这样使用:
String imageURL = "http://c.hiphotos.baidu.com/image/pic/item/0dd7912397dda1449fad6f63b6b7d0a20df486be.jpg";ImageLoaderManager.getInstance().load(mImageView,imageURL);
NetworkImageView
在Volley里除了使用 ImageRequest
和Imageloader
加载网络图片,还提供了第三种方式,那就是NetworkImageView
;它是一个自定义的View,继承自ImageView;它比其它两种方式都好用,具体用法如下:
首先 在布局里面添加
NetWorkImageView
<com.android.volley.toolbox.NetworkImageView android:id="@+id/networkImageView" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
然后在Activity里面获取这个控件
mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
最后给
NetworkImageView
设置默认图,失败图,和图片的URL;需要注意的是,在设置图片URL的时候需要用到上面的ImageLoader;代码如下:
mNetworkImageView.setDefaultImageResId(R.drawable.default_icon); mNetworkImageView.setErrorImageResId(R.drawable.error_icon); mNetworkImageView.setImageUrl(imageURL,ImageLoaderManager.getInstance().getImageLoader());
这样就OK了。
在布局里面,没有给NetworkImageView
设置具体的宽高,这样不会对图像进行压缩,如果想压缩就给它设置 android:layout_width
和android:layout_height
属性就可以了,它会在内部自动化完成。
- Volley 的介绍和使用(三)
- Volley 的介绍和使用(一)
- Volley 的介绍和使用(二)
- Volley 框架的介绍和使用
- Volley的使用(三)
- Android Volley使用介绍(三),量身定做自己的Request
- Android Volley框架的使用(三)
- Android Volley框架的使用(三)
- Volley的使用(三):Volley与Activity的联动 + Volley的二次封装
- Volley框架的介绍使用
- Volley框架的介绍使用
- Volley框架的使用介绍
- Volley的介绍和用法
- Android Volley的使用(三)Volley中如何使用https
- volley的使用【定制自己的request】(三)
- Android中关于Volley的使用(三)认识Volley的架构
- Android中关于Volley的使用(三)认识Volley的架构
- Android中关于Volley的使用(三)认识Volley的架构
- 深入FFM原理与实践
- sql 复制服务器文件
- pjsua帮助手册(中文)
- 在Ubuntu下编译FFmpeg
- [BZOJ1516] [POI2006]Mag-Warehouse
- Volley 的介绍和使用(三)
- 使用asp.net和wCF4.0开发RESTful服务
- 拓扑结构相同子树练习题
- 李克强总理为啥要在政府工作报告中提倡工匠精神?
- java IO流读写文件
- 15_Android性能优化
- java socket 通信编程
- js中巧用cssText属性批量操作样式(转)
- Android中Intent.action的各种常见作用