volley解惑

来源:互联网 发布:淘宝最低折扣0.7是什么 编辑:程序博客网 时间:2024/06/01 08:42
volley是什么?
volley是2013年Google I/O大会上推出了一个新的网络通信框架,封装了http网络请求的通信细节,能够简单的进行http请求,简单地处理网络图片。

如何使用?
a. 生成Request对象
b. 创建RequestQueue
c. 将Request加入到RequestQueue中,网络请求完成后,会有调用Request对象的回调函数。
mQueue = Volley.newRequestQueue(this);stringRequest= new StringRequest("http://www.baidu.com", new Response.Listener<String>() {    @Override    public void onResponse(String response) {        Debug.d(this, response);    }}, new Response.ErrorListener() {    @Override    public void onErrorResponse(VolleyError error) {        Debug.d(this, error.toString());    }});mQueue.add(stringRequest);

现有的Request子类有
StringRequest
JsonObjectRequest
JsonArrayRequest
ImageRequest
支持定制

如何跟踪volley的日志输出?
VolleyLog这个类来控制调试信息的输出, 默认是使用"Volley"这个tag,实际当中会定制专属自己app的tag。
默认情况下,logcat捕捉不到调试信息,需要在adb中开启log打印。
E:\ws\git\volley>adb devicesList of devices attachedA0Y9G9RTKZ      device
adb -s A0Y9G9RTKZ shell setprop log.tag.Volley VERBOSE

这个是我们写log时可以借鉴的机制。

如何修改Request的优先级?
基类Request有该方法,默认都是NORMAL级别的,继承类可以通过改写getPriority来修改优先级。

Request.java
/** * Priority values.  Requests will be processed from higher priorities to * lower priorities, in FIFO order. */public enum Priority {    LOW,    NORMAL,    HIGH,    IMMEDIATE}/** * Returns the {@link Priority} of this request; {@link Priority#NORMAL} by default. */public Priority getPriority() {    return Priority.NORMAL;}

如何取消Request?
加入队列时,
stringRequest.setTag(TAG);
mRequestQueue.add(stringRequest);
取消时
mRequestQueue.cancelAll(TAG);
比如用在ViewPager当中

特定的请求不加入缓存中
Request方法
/** * Returns true if responses to this request should be cached. */public final boolean shouldCache() {    return mShouldCache;}

删除特定url对应的缓存
AppController.getInstance().getRequestQueue().getCache().remove(url);

删除所有缓存
AppController.getInstance().getRequestQueue().getCache().clear();


Volley默认的缓存是个什么样的概念?
Volley默认使用的是磁盘缓存
Volley.java
/**     * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.     * You may set a maximum size of the disk cache in bytes.     *     * @param context A {@link Context} to use for creating the cache dir.     * @param stack An {@link HttpStack} to use for the network, or null for default.     * @param maxDiskCacheBytes the maximum size of the disk cache, in bytes. Use -1 for default size.     * @return A started {@link RequestQueue} instance.     */    public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {...        // 默认采用的是磁盘缓存---DiskBaseCache        RequestQueue queue;        if (maxDiskCacheBytes <= -1)        {        // No maximum size specified        queue = new RequestQueue(new DiskBasedCache(cacheDir), network);        }        else        {        // Disk cache size specified        queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);        }        queue.start();        return queue;    }

NetworkDispatcher.java
@Override    public void run() {...                // Parse the response here on the worker thread.                Response<?> response = request.parseNetworkResponse(networkResponse);                request.addMarker("network-parse-complete");                // 写入缓存                // Write to cache if applicable.                // TODO: Only update cache metadata instead of entire record for 304s.                if (request.shouldCache() && response.cacheEntry != null) {                    mCache.put(request.getCacheKey(), response.cacheEntry);                    request.addMarker("network-cache-written");                }...    }


使用ImageRequest来请求图片有什么好处?
ImageRequest是Request的子类,使用上来和Request一样方便。
.  返回Bitmap,
.  轻松改变图片尺寸
.  耗时的图片处理放在工作线程中


加载单个网络图片,使用ImageRequest,但是在ListView或者GridView这种使用很多图片的情形下,一般使用ImageLoader + NetworkImageView。
android sdk提供的示例代码
ImageLoader mImageLoader;NetworkImageView mNetworkImageView;private static final String IMAGE_URL =    "http://developer.android.com/images/training/system-ui.png";...// Get the NetworkImageView that will display the image.mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);// Get the ImageLoader through your singleton class.mImageLoader = MySingleton.getInstance(this).getImageLoader();// Set the URL of the image that should be loaded into this view, and// specify the ImageLoader that will be used to make the request.mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);

为什么要使用ImageLoader?
Volley默认使用的缓存是磁盘缓存,在ListView显示大量图片的情形下,使用磁盘缓存速度并不是那么令人满意,有个特定的现象叫flicker,ImageLoader引入了内存缓存,在使用volley提供的磁盘缓存之前,先在内存缓存中搜索。

为什么要使用NetworkImageView?
在ListView中显示大量图片时,ImageView是复用的,这可能出现图形错乱的现象。
NetworkImageView是ImageView的子类,会取消上一个无效的请求。

public void setImageUrl(String url, ImageLoader imageLoader) {        mUrl = url;        mImageLoader = imageLoader;        // The URL has potentially changed. See if we need to load it.        loadImageIfNecessary(false);    }    /**     * Loads the image for the view if it isn't already loaded.     * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.     */    void loadImageIfNecessary(final boolean isInLayoutPass) {        // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content        // view, hold off on loading the image....        // if the URL to be loaded in this view is empty, cancel any old requests and clear the        // currently loaded image....        // if there was an old request in this view, check if it needs to be canceled....        // Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens....        // The pre-existing content of this view didn't match the current URL. Load the new image        // from the network....        // update the ImageContainer to be the new bitmap container....    }

volley能否加载本地图片?
stack overflow 上的问答 Let Volley's NetworkImageView show local image files    
用ImageLoader是可以实现的,和普通的网络图片请求没差别,除了url是本地类型的。
使用内存缓存,根据url判断,如果是本地图片,直接加载图片。但验证了下,这一过程是在UI线程中进行的,所以不推荐使用Volley来加载本地图片
mImageLoader = new ImageLoader(mRequestQueue,new ImageLoader.ImageCache() {    private final LruCache<String, Bitmap>            cache = new LruCache<String, Bitmap>(20);    @Override    public Bitmap getBitmap(String url) {        if (url.contains("file://")) {            // url地址类似于 #W0#H0#S3file:///data/data/com.example.jacksonke.volleydemo/files/1.png            String tmppath = url.substring(url.indexOf("file://") + 7);            Bitmap bitmap = BitmapFactory.decodeFile(url.substring(url.indexOf("file://") + 7));            // TODO 处理图片尺寸            if (bitmap != null){                putBitmap(url, bitmap);            }            // 如果本地图片不存在呢?返回是null,会走volley网络请求的流程,这样是否有其他问题            // 加载图片失败,会使用默认的失败图片            return bitmap;        }        else {            return cache.get(url);        }    }    @Override    public void putBitmap(String url, Bitmap bitmap) {        cache.put(url, bitmap);    }});




0 0