Volley:google出的一个用于异步处理的框架。由于本身的易用性和良好的api,使得它能得以广泛的应用。我还是一如既往从源码的方向上来把控它。我们先通过一段简单的代码来了解Volley

RequestQueue queue = Volley.newRequestQueue(this);ImageRequest imagerequest = new ImageRequest(url, new Response.Listener<Bitmap>(){            @Override            public void onResponse(Bitmap response) {                // TODO Auto-generated method stub                System.out.println(">>>bitmap = "+response);            }}, 300,                200,                Config.ARGB_8888,                new ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        // TODO Auto-generated method stub                        System.out.println("error "+error);                    }                });        queue.add(imagerequest);

俗话说,“对比方显美”,代码框架也如此。我们先回想一下我们过去创建bitmapcache的惨痛经历吧。首先我们使用的cache功能比较单一,往往只是支持内存cache,淘汰策略一般是通过数量或者容量限制。每写一个app都自成一套。此外,一旦我们脱离了程序,我们将不再获得我们Bitmap的元数据,比如请求网络链接,资源描述符等等,而且对于同一个网络请求我们要用单独的装饰器来拦截。

当然,我之所以列举这些出来,是因为在Volley里面已经很好的解决了这些问题,当你下载了Volley的源码编译以后,你会发现,Volley所涵盖的功能远比你考虑的要多。而且这些东西,已经被很好的封装起来。而且Volley的代码读起来也非常的顺口,并不像Android原生的一些代码一样又臭又长。如果说Volley是一种好的开源框架,不如说Volley是一套现在看起来还不错的设计模式。而且从Volley所提供的有些接口来说,Volley已经将很大部分封装在框架内部,对于api调用者来说,无疑是个福音。

Volley里面普遍采用了生产消费者模式,当然你说它是观察者其实也无可厚非。生产者通过生产产品来通知消费者消费,这种简单的模型在多种框架中使用到。这里的消费者是叫Request的类。这个类将分发给CacheDispatcher和NetworkDispatcher来进行消费。从我们写Cache的经验来说我们对Cache的处理模式普遍一致,大都是看Cache中是否存在,如果存在,则load from disk.否则请求网络。其实Volley的处理大同小异。对于允许Cache的请求。Request将被RequestQueue分发到CacheDispatcher消费。如果CacheDispatcher消费不了,那么就将分发给NetworkDispatcher。这种模式非常像职责链。其实在这种分发下,存在一个Volley的亮点之一,就是url拦截。RequestQueue本身维护一个暂存列表,而这种暂存列表能很好的拦截重复的URL请求。由CacheDispatcher处理的请求,如果在disk cache中存在,那么将通过Request的parseNetworkResponse 接口进行解析,我们看一下对于一个图片请求他的parse流程:

private Response<Bitmap> doParse(NetworkResponse response) {        byte[] data = response.data;        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();        Bitmap bitmap = null;        if (mMaxWidth == 0 && mMaxHeight == 0) {            decodeOptions.inPreferredConfig = mDecodeConfig;            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);        } else {            // If we have to resize this image, first get the natural bounds.            decodeOptions.inJustDecodeBounds = true;            BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);            int actualWidth = decodeOptions.outWidth;            int actualHeight = decodeOptions.outHeight;            // Then compute the dimensions we would ideally like to decode to.            int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight,                    actualWidth, actualHeight);            int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth,                    actualHeight, actualWidth);            // Decode to the nearest power of two scaling factor.            decodeOptions.inJustDecodeBounds = false;            // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it?            // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED;            decodeOptions.inSampleSize =                findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);            Bitmap tempBitmap =                BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);            // If necessary, scale down to the maximal acceptable size.            if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth ||                    tempBitmap.getHeight() > desiredHeight)) {                bitmap = Bitmap.createScaledBitmap(tempBitmap,                        desiredWidth, desiredHeight, true);                tempBitmap.recycle();            } else {                bitmap = tempBitmap;            }        }        if (bitmap == null) {            return Response.error(new ParseError(response));        } else {            return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response));        }    }
我们看到,它产生了一个response对象返回给了上层,最后再由Delivery来分发Reponse.其实我们可以看出,整个Volley的Cache设计相对简单,而且还有很大的改造空间。比如,对于 Delivery的分发机制,完全可以用EventBus这类的事件驱动的框架来完成。还有Bitmap的生成,可以采用内存映射文件的方式来减少内存开销。当然,这些小甜点并不影响Volley做为一个非常优秀的代码而存在。在Volley里面Delivery的本质是一个线程池,采用线程池post的方式可以有效的避免Volley的CacheDispatcher和NetWorkDispatcher因为处理reponse而造成的线程阻塞。

我们再回头看看如果我们在Cache中不存在,我们请求网络的情况。Volley对平台的请求接口进行了封装,你可能采用的是HttpClient,当然也有可能是直接使用HttpUrlConnection。对于上层来说,为了屏蔽掉这种平台的差异性,抽象出一个叫做Network的网络接口,这是一种桥接的模式。而当你使用某种方式网络获得数据以后,NetworkDispatcher将数据put到Cache中.通过Delivery分发Request回调以后,调用Request的finish方法将自己从RequestQueue的暂存表中删除。

好的,是不是觉得Volley代码设计的是如此的思路清晰,本章我们先介绍Volley的主体结构,下面会通过两章节来描述Volley的两大模块:Cache和Network设计。






更多相关文章

  1. 如何解决Android(安卓)5.0中出现的警告:Service Intent must be e
  2. 【源代码】基于Android和蓝牙的单片机温度採集系统
  3. Android学习笔记2:Hello World程序解析
  4. 【源码】实现Android闹钟功能使用HTML+JS,并附带Alarm代码分享
  5. Android使用getIdentifier()方法根据资源名来获取资源id
  6. 让你的代码减少三倍!使用kotlin开发Android(五) 监听器
  7. 最完整Android(安卓)Studio插件整理 (转)
  8. 在 Android(安卓)studio 中 配置Gradle 根据不同参数打包,并在代
  9. 二、Android(安卓)NDK编程预备之Java jni入门Hello World

随机推荐

  1. android 对话框集合
  2. Android:从Eclipse到Android Studio迁移工
  3. Android AutoCompleteTextView示例教程
  4. android jni系列教程
  5. Android(安卓)6.0 Launcher3隐藏小部件与
  6. android 计算器(2)
  7. android 数据库同步
  8. Android Studio怎样清空ArrayList
  9. 设置 listview 滚动条样式
  10. Android 4+ WIFI 直连