Volley 的介绍和使用(三)
2016-03-17 16:02
471 查看
这一节我们介绍自定义Request。
在上一节中我们只介绍了
类似我们创建一个JsonPostRequest:
这样我们就可以得到一个请求返回是JSONObject的请求类了。我们可以这样使用它。
使用方式类似于之前的
所以我们需要一个
上面的方法的第一个参数,是要显示图片的控件;第二个参数是默认图;第三个图片是下载失败要显示的图片。
最后我们只需要在调用
上面说的比较简单,下面我们上代码。
上面只是一个简单的应用,还没有用到
我们继承及成LruCache并且实现了ImageCache接口,设置了图片的缓存大小。我使用的时候可以下面这样:
有没有感觉这样太麻烦了,每次都要写这么一大堆,当我们把ImageCache实现之后,可以把相应的代码抽取出来,做一个单例类,每次使用的时候只需要一样代码就可以实现。具体代码如下:
当我们可以这样使用:
首先 在布局里面添加
然后在Activity里面获取这个控件
最后给
这样就OK了。
在布局里面,没有给
在上一节中我们只介绍了
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属性就可以了,它会在内部自动化完成。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories