Android Volley分析(二)——实现

在Android Volley分析(一)——结构中主要分析了Volley的基本组件和框架结构,组件主要是定义的接口,也就是说我们可以实现这些接口来定制自己的Volley版本,比如NetWork、Cache、Request等等。Android Volley在com.android.volley.toolbox下已经做了这些工作,下面就看看这些具体的实现内容

先看一个Volley使用的例子

final TextView mTextView = (TextView) findViewById(R.id.text);
...

// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";

// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener() {
    @Override
    public void onResponse(String response) {
        // Display the first 500 characters of the response string.
        mTextView.setText("Response is: "+ response.substring(0,500));
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        mTextView.setText("That didn't work!");
    }
});
// Add the request to the RequestQueue.
queue.add(stringRequest);

这是官方volley教程的一个例子,使用Volley的步骤

1、Volley.newRequestQueue();

2、new Request();

3、queue.add(request);

在newRequestQueue的时候会初始化基本的组件

    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;
    }

1、BasicNetwork

BasicNetwork是对Network接口的实现,同时还将联网操作部分提取出来形成HttpStack,原因是Android 2.3之前网络操作推荐使用HttpClient,2.3之后Android做了优化推荐使用HttpUrlConnection。

2、DiskBasedCache

DiskBasedCache是对Cache对实现,用于硬盘缓存,也就是将数据保存为特定的文件。

结合LruCache试着总结一下缓存的一般方法:

映射结构——LinkedHashMap,内部实现了Lru的算法排序,可以直接使用

put——存储,容量计数增加,判断是否超出最大容量,超出则删除最少使用的

get——key到entry的映射

remove——删除,容量计数减小

3、ImageLoader

ImageLoader是一个图片加载类,封装了请求,提供了内存缓存机制,批处理等,让图片加载更容易使用,下面看一下它的用法:

        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
         R.drawable.def_image, R.drawable.err_image));

(示例来源 Making a Standard Request )

内存缓存推荐使用LruCache,需要实现ImageLoader.ImageCache接口。图片的加载通过imageLoader.get()方法实现,

    public ImageContainer get(String requestUrl, ImageListener imageListener,
            int maxWidth, int maxHeight) {
        // only fulfill requests that were initiated from the main thread.
        throwIfNotOnMainThread();

        final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);

        // Try to look up the request in the cache of remote images.
        Bitmap cachedBitmap = mCache.getBitmap(cacheKey);
        if (cachedBitmap != null) {
            // Return the cached bitmap.
            ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null);
            imageListener.onResponse(container, true);
            return container;
        }

        // The bitmap did not exist in the cache, fetch it!
        ImageContainer imageContainer =
                new ImageContainer(null, requestUrl, cacheKey, imageListener);

        // Update the caller to let them know that they should use the default bitmap.
        imageListener.onResponse(imageContainer, true);

        // Check to see if a request is already in-flight.
        BatchedImageRequest request = mInFlightRequests.get(cacheKey);
        if (request != null) {
            // If it is, add this request to the list of listeners.
            request.addContainer(imageContainer);
            return imageContainer;
        }

        // The request is not already in flight. Send the new request to the network and
        // track it.
        Request<?> newRequest =
            new ImageRequest(requestUrl, new Listener<Bitmap>() {
                @Override
                public void onResponse(Bitmap response) {
                    onGetImageSuccess(cacheKey, response);
                }
            }, maxWidth, maxHeight,
            Config.RGB_565, new ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    onGetImageError(cacheKey, error);
                }
            });

        mRequestQueue.add(newRequest);
        mInFlightRequests.put(cacheKey,
                new BatchedImageRequest(newRequest, imageContainer));
        return imageContainer;
    }

首先得到一个cacheKey,这个是统一的规则

    private static String getCacheKey(String url, int maxWidth, int maxHeight) {
        return new StringBuilder(url.length() + 12).append("#W").append(maxWidth)
                .append("#H").append(maxHeight).append(url).toString();
    }

然后在缓存cache中查找,没找到就讲请求添加到批处理任务BitmapImageRequest中,这里有两个类,ImageContainer和BitmapImageRequest:

ImageContainer是一个包装类,里面包含了bitmap、url、cacheKey和listener,当得到bitmap后会通过listener将bitmap返回;

BitmapImageRequest是将相同url请求放在一起,这样就可以只向网络请求一次,返回结果后再分别设置到目标上,从而达到减少网络请求对目的。

时间: 2024-12-17 21:38:57

Android Volley分析(二)——实现的相关文章

Android Binder分析二:Natvie Service的注冊

这一章我们通过MediaPlayerService的注冊来说明怎样在Native层通过binder向ServiceManager注冊一个service,以及client怎样通过binder向ServiceManager获得一个service,并调用这个Service的方法. Native Service的注冊 这里以MediaPlayerService举例来说明怎样在Native层注冊Service,首先来看main_mediaservice.cpp的main方法: int main(int a

Android Volley分析(一)

Volley是Android系统下的一个网络通信库,为Android提供简单快速的网络操作(Volley:Esay, Fast Networking for Android),下面是它的结构: 既然是网络通信库,自然会涉及到网络的基础操作:请求和响应,也是最基本的概念.客户端发出请求,服务端返回响应的字节数据,客户端解析得到想要的结果.Volley怎么设计这些基本的概念? 一.组件 1.Network 网络操作的定义,传入请求Request,得到响应NetworkResponse public

Android WifiDisplay分析二:Wifi display连接过程.

这一章中我们来看Wifi Display连接过程的建立,包含P2P的部分和RTSP的部分,首先来大致看一下Wifi Display规范相关的东西. HIDC: Human Interface Device Class  (遵循HID标准的设备类)UIBC: User Input Back Channel  (UIBC分为两种,一种是Generic,包含鼠标.键盘等:另一种是HIDC,HID是一个规范,只有遵循HID的标准,都可以叫做HID设备,包含USB鼠标.键盘.蓝牙.红外等)PES: Pac

Android测试分析二

什么是android测试,分为黑盒测试和白盒测试. 黑盒就是测试人员看不到代码的,针对需求而进行的一系列测试动作,看代码所展现出来的效果是否和需求一样,或者有什么意外的情况没有处理等,一般开发交给测试人员,测试人员经过半天或者一天测试后,会返回一个测试的excel表单,里面有一条条的bug单,或者显示和功能不匹配,或者出现闪退等意外没有处理等等,开发人员根据bug单去修复就可以了.这里面蕴含了一个软件需求转换成测试需求,开发人员满足测试需求的关系了.有点类似听到的TDD(test-drive-d

Android WIFI 分析(二)

本文介绍Wifi 分析线路二:在Setting中打开WiFi功能.扫描网络以及连接网络的流程. WifiSettings 无线网络设置界面 WifiEnabler 相当于无线网络设置开关 WifiDialog 显示的无线网络配置信息由WifiConfigController 来控制和管理 Scanner 用于处理和无线网络扫描相关的工作 1.Settings 操作 无线网络设置界面UI 初始化过程中,WifiSettings 的onActivityCreated() 方法被调用: public

Android Scroll分析 (二) 教你使用七种方法实现滑动

实现滑动的基本思想是:当触摸View时,系统记下当前触摸点坐标;当手指移动时,系统记下移动后的触摸点坐标,从而获取到相对于前一次坐标点的偏移量,并通过偏移量来修改View的坐标,这样不断重复,从而实现滑动过程. 2.1 Layout方法 在View进行绘制时,会调用onLayout()方法来设置显示的位置 通过修改View的left,top,right,bottom四个属性来控制View的坐标,在每次回调onTouchEvent的时候,获取一下触摸点的坐标: // 视图坐标方式 @Overrid

Android Telephony分析(六) ---- 接口扩展(实践篇)

本文将结合前面五篇文章所讲解的知识,综合起来,实现一个接口扩展的功能.如果还没有阅读过前面五篇文章的内容,请先阅读:<Android Telephony分析(一) — Phone详解 ><Android Telephony分析(二) — RegistrantList详解 ><Android Telephony分析(三) — RILJ详解 ><Android Telephony分析(四) — TelephonyManager详解 ><Android Te

[Android]Volley源码分析(二)Cache

Cache作为Volley最为核心的一部分,Volley花了重彩来实现它.本章我们顺着Volley的源码思路往下,来看下Volley对Cache的处理逻辑. 我们回想一下昨天的简单代码,我们的入口是从构造一个Request队列开始的,而我们并不直接调用new来构造,而是将控制权反转给Volley这个静态工厂来构造. com.android.volley.toolbox.Volley: public static RequestQueue newRequestQueue(Context conte

[Android]Volley源码分析(二)

上一篇介绍了Volley的使用,主要接触了Request与RequestQueue这两个类,这篇就来了解一下这两个类的具体实现. Request类图: Request类: Request是一个抽象类,其中的主要属性: mMethod: 请求方法,目前支持GET, POST, PUT, DELETE, HEAD, OPTIONS,TRACE, PATCH方法 mUrl: 请求Url mErrorListener: 错误处理监听器,请求出错时调用 mSequence: 请求的序号,相同优先级的请求在