Volley全解析

来源:互联网 发布:师洋淘宝店骂人 编辑:程序博客网 时间:2024/06/05 03:08

什么是Volley

  • Volley 的单词涵义是:迸发、万箭齐发。 是比喻的命名方式,寓指网络请求并发效率高。

Volley 的重要方法

  • mQueue = Volley.newRequestQueue(context);
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);        String userAgent = "volley/0";        try {            String packageName = context.getPackageName();            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);            userAgent = packageName + "/" + info.versionCode;        } catch (NameNotFoundException e) {        }        if (stack == null) {            if (Build.VERSION.SDK_INT >= 9) {                stack = new HurlStack();            } else {                // Prior to Gingerbread, HttpUrlConnection was unreliable.                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));            }        }        Network network = new BasicNetwork(stack);        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);        queue.start();        return queue;    }
  • Volley 在新建RequestQueue 的时候,其实是新建了两个 Queue, 一个CacheQueue(用于获取获取本地缓存结果),一个NetworkQueue(用于网络请求); 在 queue.start(); 中, start 的是 一个 CacheDispatcher 和 4个 NetworkDispatcher, 分别作用在前面的两个Queue

  • mQueue = Volley.newRequestQueue(context); 最好放在 Application 中,整个app 只有一个requestQueue.

  • new ExecutorDelivery(new Handler(Looper.getMainLooper())) 在RequestQueue 的参数中,有一个delivey 将handler 传入其中,后面就是通过handler 的post 在主线程中回调 Listener 的。

  • 需要注意一下的是,网络请求,在android 版本2.2 以前建议使用的是 httpclient, 而在 2.2 以后建议使用的是HttpUrlConnection 。 5.2 以后,若使用 HttpClient 会出现通篇的warning, 这是因为google 已经强烈要求使用 HttpUrlConnection 了。 原因是: HttpUrlConnection 相比于 HttpClient 体积更小,API 更为简单,而且扩展性比HttpClient 好很多,在压缩、缓存、省电、减少流量等各方面都要突出一些。 所以HttpUrlConnection 更适用于 android。

  • mQueue.add(new Request());
    /**     * Adds a Request to the dispatch queue.     * @param request The request to service     * @return The passed-in request     */    public Request add(Request request) {        // Tag the request as belonging to this queue and add it to the set of current requests.        request.setRequestQueue(this);        synchronized (mCurrentRequests) {            mCurrentRequests.add(request);        }        // Process requests in the order they are added.        request.setSequence(getSequenceNumber());        request.addMarker("add-to-queue");        // If the request is uncacheable, skip the cache queue and go straight to the network.        if (!request.shouldCache()) {            mNetworkQueue.add(request);            return request;        }        // Insert request into stage if there's already a request with the same cache key in flight.        synchronized (mWaitingRequests) {            String cacheKey = request.getCacheKey();            if (mWaitingRequests.containsKey(cacheKey)) {                // There is already a request in flight. Queue up.                Queue<Request> stagedRequests = mWaitingRequests.get(cacheKey);                if (stagedRequests == null) {                    stagedRequests = new LinkedList<Request>();                }                stagedRequests.add(request);                mWaitingRequests.put(cacheKey, stagedRequests);                if (VolleyLog.DEBUG) {                    VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);                }            } else {                // Insert 'null' queue for this cacheKey, indicating there is now a request in                // flight.                mWaitingRequests.put(cacheKey, null);                mCacheQueue.add(request);            }            return request;        }    }
  • Request 是完全可以自定义的。Volley 提供的 Request 有 StringRequest 、 JsonObjectRequest、 JsonArrayRequest、 ImageRequest 等等。

  • 往Queue中添加Request 的过程是: 先判断 Request 的 shouldCache 属性,如果该属性为 true 则将 Request 添加到 CacheQueue 中,当然其中会有 waitingRequest 的 list 来控制相同的 请求不再重复添加。 如果该属性为 false, 则直接加入到 NetworkRequest 中。如果本地没有缓存,即在CacheQueue处理过后,发现没有数据,则重新添加到NetworkQueue 中。 在请求数据回来之后,再次判断 showCache 来写缓存及返回数据到UI线程。

自定义Request

  • 覆盖 ContentType 属性
    @Override    public String getBodyContentType() {//        super.getBodyContentType();        return "application/json";    }
  • 覆盖 getBody() , Volley 默认的添加 content params 的方法是添加 “&”等等,与我们经常使用的是不一样的,所以覆盖 getParams() 还达不到我们想要的效果,所以直接覆盖 getBody() 方法。
        if (mParams != null && !mParams.isEmpty()) {            String ss = JSON.toJSONString(mParams);            return ss.getBytes();        }        return super.getBody();
  • 添加自定义 header
    @Override    public Map<String, String> getHeaders() throws AuthFailureError {        return mHeaderParams;    }
  • 结果处理
    @Override    protected Response<T> parseNetworkResponse(NetworkResponse response) {        // 在这处理    }
  • 其他

默认的 get 请求, 传入的 params 不会被处理,所以需要在外面将 url 自行拼接好再传入 Volley 中。

   private String toGetUrl(String url, Map<String, Object> entity) {        StringBuilder urlSB = new StringBuilder();        if (entity != null && !entity.isEmpty()) {            for (String key : entity.keySet()) {                if (urlSB.length() != 0) {                    urlSB.append("&");                }                urlSB.append(key + "="                        + Uri.encode(JSON.toJSONString(entity.get(key))));            }        }        if (urlSB == null || "".equals(urlSB.toString())) {            return url;        }        return url + "?" + urlSB.toString();    }
  • 常用属性设置
        setShouldCache(false);        setRetryPolicy(                // 超时时间、retry次数、超时时间乘数 例如第一次5秒  第二次超时想要设置10秒, 乘数就为2 默认为1 可以是float                new DefaultRetryPolicy(5000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)        );        setTag("tag"); // 标记 可用于cancle request

ImageLoader、 NetworkImageView

        mNetworkImageView.setDefaultImageResId(R.drawable.ic_launcher); // 默认图片        mNetworkImageView.setErrorImageResId(R.drawable.ic_launcher); // 发生错误时        mNetworkImageView.setImageUrl(URLS[1], MyApplication.genImageLoader());// 请求地址,及 imageloader
  • MyApplication
    @Override    public void onCreate() {        super.onCreate();        mInstance = this;        mQueue = Volley.newRequestQueue(this);        VolleyImageCache lruImageCache = VolleyImageCache.genInstance();        mImageLoader = new ImageLoader(mQueue,lruImageCache);    }
  • VolleyImageCache
public class VolleyImageCache implements ImageLoader.ImageCache {    private static LruCache<String, Bitmap> mMemoryCache;    private static VolleyImageCache mVolleyImageCache = new VolleyImageCache();    private VolleyImageCache() {        // Get the Max available memory        int maxMemory = (int) Runtime.getRuntime().maxMemory();        int cacheSize = maxMemory / 8;        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {            @Override            protected int sizeOf(String key, Bitmap bitmap) {                return bitmap.getRowBytes() * bitmap.getHeight();            }        };    }    public static VolleyImageCache genInstance() {        return mVolleyImageCache;    }    @Override    public Bitmap getBitmap(String arg0) {        return mMemoryCache.get(arg0);    }    @Override    public void putBitmap(String arg0, Bitmap arg1) {        if (getBitmap(arg0) == null) {            mMemoryCache.put(arg0, arg1);        }    }}

使用Volley 上传文件

    private MultipartEntity mReqEntity = new MutipartEntity();    @Override    public String getBodyContentType() {        return mReqEntity.getContentType().getValue();    }    @Override    public byte[] getBody() throws AuthFailureError {        if (!CollectionUtils.isCollectionEmpty(mFilePath)) {            // upload files            ByteArrayOutputStream bos = new ByteArrayOutputStream();            try {                mReqEntity.writeTo(bos);            } catch (IOException e) {                VolleyLog.e("IOException writing to ByteArrayOutputStream");            }            return bos.toByteArray();        }           return super.getBody();     }    private void buildMultipartEntity() {        try {            for (String filepath : mFilePath) {                File file = new File(filepath);                FileBody filePart = new FileBody(file);                mReqEntity.addPart(file.getName(), filePart);            }            if (mParams != null && !mParams.isEmpty()) {                Iterator<String> keySet = mParams.keySet().iterator();                while (keySet.hasNext()) {                    String key = keySet.next();                    String ss = JSON.toJSONString(mParams.get(key));                    mReqEntity.addPart(key, new StringBody(ss));                }            }        } catch (UnsupportedEncodingException e) {        // empty here        }    }
0 0
原创粉丝点击