Volley的初步了解
阅读原文时间:2023年07月12日阅读:2

Volley的介绍

  • Volley是什么?

    • 2013年Google I/O大会上推出的网络请求和图片加载框架
    • 其优点是api简单,性能优秀
    • 非常适合数据量不大但是通信频繁的网络请求,而对于大数据量的操作,如文本下载,表现则没有那么好
    • Volley内部仍然是使用的HttpURLConnection和HttpClient进行网络请求的,只是对于不同的Android版本进行了响应的切换,2.3之前使用的HttpClient,2.3之后使用的是HttpURLConnection 这是因为在2.3版本之前,HttpURLConnection有一个很严重的bug,当开启请求的时候会造成线程池无法关闭。
  • 为什么用Volley,相比XUtil,Volley解决了以下问题:

    • 当用户finish当前的Activity的时候,而当前Activity正在进行网络请求,Volley支持取消网络请求
    • 当用户旋转屏幕,Activity重新创建,那么同样的网络请求会从新发送,而Volley支持对重复的请求进行缓存
    • 支持多样的网络请求返回封装

3. Volley的使用

  • 首先,引入Volley类库,添加相关权限



  • Volley中的核心类

    • Request,请求类,有几个实现类

      • StringRequest:请求的时候直接回来一个String
      • JsonObjectRequest:请求的时候直接回来一个JsonObject
      • JsonArrayRequest:请求的时候直接回来一个JsonArray
      • ImageRequest:请求的时候直接回来一个Bitmap
      • 自定义请求:一会我们会结合gson
    • RequestQueue:请求队列,用来执行Request的

    • ImageLoader:图片加载的类

    • NetWorkImageView:继承自ImageView,可以直接加载网络图片

  • 创建请求队列RequestQueue

    RequestQueue queue = Volley.newRequestQueue(this);

  • 使用StringRequest进行请求

    //2.创建网络请求
    StringRequest stringRequest = new StringRequest(url, new Listener() {
    @Override
    public void onResponse(String response) {
    tv_result.setText(response);
    }
    },new MyErrorListener());
    //3.执行请求
    queue.add(stringRequest);

  • 使用JsonRequest进行请求

    //1.创建JsonRequest请求
    JsonObjectRequest joRequest = new JsonObjectRequest(url, null, new Listener() {
    @Override
    public void onResponse(JSONObject response) {
    tv_result.setText(response.toString());
    }
    }, new MyErrorListener());
    //2.执行请求
    queue.add(joRequest);

  • 使用JsonArrayRequest进行请求

    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(listUrl, new Listener() {
    @Override
    public void onResponse(JSONArray response) {
    tv_result.setText(response.toString());
    }
    }, new MyErrorListener());
    queue.add(jsonArrayRequest);

  • 使用ImageRequest进行请求

    ImageRequest imageRequest = new ImageRequest(imageUrl,new Listener() {
    @Override
    public void onResponse(Bitmap response) {
    iv_result.setImageBitmap(response);
    }
    }, 200, 100, Config.RGB_565, new MyErrorListener());
    queue.add(imageRequest);

4. 加载图片的压缩处理的核心

  • 第一步: 从原图进行等宽高比的采样,采样的值最好是2的倍数,代码如下:

    Options opts = new Options();
    opts.inSampleSize = 4;
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);

  • 第二步: 根据图片的原始宽高比和控件的宽高比,科学的计算采样比例,代码如下:

    Options opts = new Options();
    opts.inJustDecodeBounds = true;//设置只解析图片的边界参数,即宽高
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);
    //科学计算图片所需的采样比例
    opts.inSampleSize = caculateSampleSize(opts.outWidth,opts.outHeight);

    opts.inJustDecodeBounds = false;//关闭标记,解析真实的图片
    bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fast, opts);

    /**
    * 根据图片的原始宽高比和ImageView的宽高计算图片的采样比例
    * @param outWidth
    * @param outHeight
    * @return
    */
    private int caculateSampleSize(int outWidth, int outHeight) {
    int inSampleSize = 1;
    if(outWidth>outHeight){
    //参考宽进行缩放
    inSampleSize = outWidth/iv_result.getWidth();//1920/300
    }else{
    //参考高进行缩放
    inSampleSize = outHeight/iv_result.getHeight();
    }
    if(inSampleSize<1){
    inSampleSize = 1;
    }
    return inSampleSize;
    }

  • 第三步: 设置图片加载的渲染模式为Config.RGB_565,能降低一半内存:

    opts.inPreferredConfig = Config.RGB_565

5. Volley中的ImageLoader使用以及内存缓存详解

  • 使用ImageLoader加载图片

    protected void loadImage() {
    ImageListener imageListener = ImageLoader.getImageListener(iv_result, R.drawable.ic_launcher, R.drawable.ic_launcher);
    MemoryCache imageCache = new MemoryCache();
    ImageLoader imageLoader = new ImageLoader(queue, imageCache);
    imageLoader.get(imageUrl, imageListener);
    }
    /**
    * 图片内存缓存
    * @author lxj
    *
    */
    public class MemoryCache implements ImageCache{
    private LruCache lruCache;
    //app可用内存的8分之一
    private int maxSize = (int) (Runtime.getRuntime().totalMemory()/8);
    public MemoryCache(){
    lruCache = new LruCache(maxSize){
    @Override
    protected int sizeOf(String key, Bitmap value) {
    return value.getHeight()*value.getRowBytes();
    }
    };
    }
    @Override
    public Bitmap getBitmap(String url) {
    return lruCache.get(url);
    }

    @Override  
    public void putBitmap(String url, Bitmap bitmap) {  
        lruCache.put(url, bitmap);  
    }  

    }

  • 内存缓存详解

    • 内存缓存的存储结构:一般是map,因为需要存取

    • 在Android2.3之前还没有好的内存缓存策略出现,一般采用SoftRefrence对Bitmap进行包装,能尽量保证不会出现oom,几种引用的解释如下:

      • 强引用 : 引用默认就是强引用, 即使内存oom, 也不会去回收对象

      • 软应用:使用SoftRefrence去包装一个对象,内存不足的时候去回收对象,尽量保证不oom,代码如下:

        HashMap> map = new HashMap>();
        SoftReference reference = map.get(url);
        Bitmap bitmap = reference.get();

      • 弱引用:使用WeakReference保证一个对象,一般不用

    • 在Android2.3之后Google提供了Lru算法的实现类,即LruCache,并推荐我们使用LruCache来实现图片的内存缓存,该类有效解决了Android中图片内存缓存的难题,常见几种内存缓存策略有:

      • Least Frequently Used(LFU): 删除使用频率最少的
      • Least Recently Used(LRU): 删除最近最少使用的
      • First in First out(FIFO): 删除最先添加进来的
      • Most Recently Used(MRU): 删除最近最多使用的
    • LruCache内部实现原理(重点)

      • 内部使用按照访问顺序排序的LinkedHashMap来存储数据
      • 每次缓存命中,该条会按照元素的访问次数进行重新排序
      • 并会判断缓存size是否超出maxSize,如果超出则移除最下方的数据,即最少使用的数据
      • 我们必须实现sizeOf方法,用来指定每条数据的size,此处是返回bitmap的大小
    • 了解XUtil等开源类库对图片内存缓存的实现

    • 了解图片的磁盘缓存的实现DiskLruCache

6. Volley中的NetworlImageView的使用

MemoryCache imageCache = new MemoryCache();
ImageLoader imageLoader = new ImageLoader(queue, imageCache);
net_imageview.setImageUrl(imageUrl, imageLoader);

7. 自定义Volley的Request

  • 我们在开发中更多的是请求一个url,然后将结果解析为java bean,所以封装一个具有该功能的Request类,GosnRequest

  • 代码如下:

    protected void execGsonRequest() {
    GsonRequest gsonRequest = new GsonRequest(url, Stu.class, new Listener() {
    @Override
    public void onResponse(Stu stu) {
    tv_result.setText(stu.toString());
    }
    }, new MyErrorListener());
    queue.add(gsonRequest);
    }
    public class GsonRequest extends Request{
    private Class clazz;
    private final Listener mListener;
    public GsonRequest(String url,Class clazz,Listener listener, ErrorListener errorListener) {
    super(url, errorListener);
    mListener = listener;
    this.clazz = clazz;
    }
    @Override
    protected Response parseNetworkResponse(NetworkResponse response) {
    String parsed;
    try {
    parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
    } catch (UnsupportedEncodingException e) {
    parsed = new String(response.data);
    }
    //解析json,返回response
    T t = new Gson().fromJson(parsed,clazz );
    return Response.success(t, HttpHeaderParser.parseCacheHeaders(response));
    }
    @Override
    protected void deliverResponse(T response) {
    mListener.onResponse(response);
    }
    }

8. 使用Volley取消网络请求

  • 给每个Request添加tag标识

    stringRequest.setTag(this);

  • 调用取消请求的方法

    queue.cancelAll(this);

9. 使用Volley发送post请求,需要自己重写Request的getParams方法

public class PostReuqest extends StringRequest {
private Map params;
public PostReuqest(String url, Response.Listener listener, Response.ErrorListener errorListener) {
super(url, listener, errorListener);
}
public PostReuqest(int method,String url, Response.Listener listener, Response.ErrorListener errorListener) {
super(method,url, listener, errorListener);
}
public void setParams(Map params){
this.params = params;
}
@Override
protected Map getParams() throws AuthFailureError {
return params;
}
}

PostReuqest stringRequest = new PostReuqest(Request.Method.POST,Api.LOGIN, new com.android.volley.Response.Listener<String>() {  
    @Override  
    public void onResponse(String response) {  
        text.setText(response);  
    }  
}, new com.android.volley.Response.ErrorListener() {  
    @Override  
    public void onErrorResponse(VolleyError error) {

    }  
});  
HashMap<String,String> map = new HashMap<>();  
map.put("username","hehehe");  
map.put("password","12321");  
stringRequest.setParams(map);

10. 对Volley进行二次封装

/**
* Volley的二次封装类
* @author lxj
*
*/
public class VolleyHelper {
private RequestQueue requestQueue;
MemoryCache imageCache = new MemoryCache();
private static VolleyHelper mInstance = null;
private VolleyHelper(Context context){
requestQueue = Volley.newRequestQueue(context);

}  
public static VolleyHelper get(Context context){  
    if(mInstance==null){  
        mInstance = new VolleyHelper(context);  
    }  
    return mInstance;  
}  
public <T> void executeRequest(Request<T> request){  
    requestQueue.add(request);  
}  
/\*\*  
 \* 执行GsonRequest  
 \* @param url  
 \* @param clazz  
 \* @param listener  
 \* @param errorListener  
 \*/  
public <T> void executeGsonRequest(String url,Class<T> clazz,Listener<T> listener,ErrorListener errorListener){  
    GsonRequest<T> gsonRequest = new GsonRequest<T>(url, clazz, listener, errorListener);  
    gsonRequest.setTag(url);  
    requestQueue.add(gsonRequest);  
}  
/\*\*  
 \* 取消请求  
 \* @param tag  
 \*/  
public void cancelRequest(String tag){  
    requestQueue.cancelAll(tag);  
}  
/\*\*  
 \* 加载图片  
 \* @param imageUrl  
 \* @param imageView  
 \*/  
public void loadImage(String imageUrl,ImageView imageView){  
    ImageListener imageListener = ImageLoader.getImageListener(imageView, R.drawable.ic\_launcher, R.drawable.ic\_launcher);  
    ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);  
    imageLoader.get(imageUrl, imageListener);  
}  

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章