Volley的使用
1.Volley的特点:
1.异步获取网络数据(Json、图片); 2.和Activity生命周期联动,多级别请求的取消。 3.支持网络图片本地存储,Lrucache 4.支持访问排序。
2.Volley中两个核心类:Request、RequestQueue
* 3.Volley三部曲
1.创建对应的请求对象(StringRequest、JsonObjectRequest、JsonArrayRequest、ImageRequest)
2.创建请求队列:RequestQueue
3.发起网络请求:queue.add(request)
4.ImageRequest
int maxWidth = 120;//0显示原始图片大小,指定大小,会对图片压缩处理 int maxHeight = 120; new ImageRequest(maxWidth,maxHeight) Config参数类型说明 Config.ALPHA_8->8位->一个字节 Config.ARGB_4444:16位 2个字节 ARGB_8888 32位 4个字节 RGB_565 16位 2个字节 有一张图片 320 * 480像素,占用内存多大呢? RGB_565: 320 * 480 * 2字节 = 307200/1024 kb ARGB_8888: 320* 480 * 4 字节 图片格式选择: Volley使用RGB_565 xutil:RGB_565 UIL:ARGB_8888 发现有时候真实图片大小和内存中不一致:是因为图片格式不一样,有点图片带有头信息
5.图片压缩核心内容
BitmapFactory.Options decodeOptions.inJustDecodeBounds = true;// 获得图片宽度和高度,图片不加载到内 存 中,图片很大也不会OOM decodeOptions.inJustDecodeBounds = false;// 加载到内存中 decodeOptions.inSampleSize:采样率,2的几次方,8 1/8发小
6.volley中的inSampleSize计算方式
static int findBestSampleSize( int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { double wr = (double) actualWidth / desiredWidth; double hr = (double) actualHeight / desiredHeight; double ratio = Math.min(wr, hr); float n = 1.0f; while ((n * 2) <= ratio) { n *= 2; } return (int) n; }
7.xutil的inSample的算法
final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (width > maxWidth || height > maxHeight) { if (width > height) { inSampleSize = Math.round((float) height / (float) maxHeight); } else { inSampleSize = Math.round((float) width / (float) maxWidth); } final float totalPixels = width * height; final float maxTotalPixels = maxWidth * maxHeight * 2; while (totalPixels / (inSampleSize * inSampleSize) > maxTotalPixels) { inSampleSize++; } } return ;
8.Universal Image Loader的inSample的算法
final int srcWidth = srcSize.getWidth(); final int srcHeight = srcSize.getHeight(); final int targetWidth = targetSize.getWidth(); final int targetHeight = targetSize.getHeight(); int scale = 1; switch (viewScaleType) { case FIT_INSIDE: if (powerOf2Scale) { final int halfWidth = srcWidth / 2; final int halfHeight = srcHeight / 2; while ((halfWidth / scale) > targetWidth || (halfHeight / scale) > targetHeight) { // || scale *= 2; } } else { scale = Math.max(srcWidth / targetWidth, srcHeight / targetHeight); // max } break; case CROP: if (powerOf2Scale) { final int halfWidth = srcWidth / 2; final int halfHeight = srcHeight / 2; while ((halfWidth / scale) > targetWidth && (halfHeight / scale) > targetHeight) { // && scale *= 2; } } else { scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min } break; } if (scale < 1) { scale = 1; } scale = considerMaxTextureSize(srcWidth, srcHeight, scale, powerOf2Scale); return scale;
universal image loader的使用
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)//缓冲到内存
.cacheOnDisk(true)//缓冲到本地
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
imageLoader.displayImage(datas.get(position).url, holder.image, options);
NetWorkImageView的使用
NetWorkImageView:显示网络图片
netWorkImg.setImageUrl(url , imageLoader);
1.ImageCache
RequestQueue queue = Volley.newRequestQueue(context);
ImageCache imageCache = new MyImageCache();
ImageLoader imageLoader = new ImageLoader(queue , imageCache);
netImage.setImageUrl(url, imageLoader );
图片内存缓冲核心:
public Bitmap getBitmap(String url);
public void putBitmap(String url, Bitmap bitmap);
2.缓存需要考虑的问题:
选择存储结构:Set、Map、List
存储图片特点:key-value形式,只有Map<K,V>符号,
3.四种引用级别
(1)强引用:平时使用的集合,比如ArrayList、HashMap、HashSet
特点:oom不回收内存
(2)软引用:SoftReference,HashMap<String, SoftReference<Bitmap>>
特点:内存不足,回收对象
以前开发使用软引用缓冲图片:2.3之后,Avoid Soft References for Caching,建议使用LruCache代替。
Most applications should use an android.util.LruCache instead of soft references.
(3)虚引用:形同虚设
(4)弱引用:不使用
4.分析LruCache
(1)LRU:least recently used,最近最少使用
(2)为什么使用LinkedHashMap作为存储结构,
new LinkedHashMap<K, V>(0, 0.75f, true):
0, 0.75f, true
第一个参数:初始化容器大小
第二个参数:负载因子,比如初始化容器大小16,负载因子0.75,16 * 0.75=12,当容器有 12个元素时,自动增长。
第三个参数:true代表按照最近访问顺序排序(LruCache选择LinkedHashMap的核心原因),false按照插入顺序排序
图片说明
5.如何使用LruCache
(1)初始化LruCache,指定缓存大小,返回bitmap实例大小
int maxSize = 6 * 1024 * 1024;// 单位:byte, 字节
// int maxSize = 6;// 单位:M
caches = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();// 图片字节大小
// return value.getByteCount()/1024/1024;// M
}
};
(2)处理存和取
@Override
public Bitmap getBitmap(String url) {
return caches.get(url);# #
}
/**将bitmap存储到内存中*/
@Override
public void putBitmap(String url, Bitmap bitmap) {
caches.put(url, bitmap);
}
Volley中的ImageLoader(现在开发中都是用UIL)
可以用来显示网络图片
RequestQueue queue = Volley.newRequestQueue(this);
ImageLoader imageLoader = new ImageLoader(queue , new MyImageCache());
String url = "http://192.168.199.238:8080/imgs/car5.PNG";
imageLoader.get(url, new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
Bitmap bitmap = response.getBitmap();
mImageView.setImageBitmap(bitmap);
}
});
自定义Request
真实项目中服务器返回的字段非常多,不可能一个个解析
gson
如何自定义request
自定义GsonRequest:
1.参考StringRequest
2.处理两个核心方法
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
Gson gson = new Gson();
T result = gson.fromJson(parsed, clazz);// 将字符串映射成Bean对象
return Response.success(result,
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError());
}
}
/** 传递数据,回调(Activity回调该方法) */
@Override
protected void deliverResponse(T response) {
mListener.onResponse(response);
}
自定义Volley请求2
public class NetResponse {
public static <T> T parseObject(Class<T> clazz, String response){
return JSON.parseObject(response, clazz);
}
public static <T> List<T> parseList(Class<T> clazz, String response){
return JSON.parseArray(response, clazz);
}
}
Volley和Activity声明周期绑定
HttpClient如何停止网络请求:HttpClient -> getConnectiontManager
ClientConnectionManager.shutdown()停止访问网络
Volley取消网络
(1)调用request的cancel方法
(2)RequestQueue cancleAll(nul)取消所有网络,
cancleAll(tag)取消对应的tag网络,request.setTag(tag)
总结Volley
- 两个核心类:Request、RequestQueue
- 四大请求:StringRequest、JsonObjectRequest、JsonArrayRequest、ImageRequest
- 加载网络图片:NetWorkImageView
- 图片缓存:LinkHashMap,Lru算法,LruCache
- 绑定页面生命周期:设置tag,取消callAll(tag)
- Volley封装好很过功能:缓存、生命周期
- Volley二次封装:为了后期拓展,提高可维护性