volley解惑

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 devices
List of devices attached
A0Y9G9RTKZ      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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值