android开源项目:图片下载缓存库picasso

picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能。

picasso有如下特性:

  • 在adapter中回收和取消当前的下载;
  • 使用最少的内存完成复杂的图形转换操作;
  • 自动的内存和硬盘缓存;
  • 图形转换操作,如变换大小,旋转等,提供了接口来让用户可以自定义转换操作;
  • 加载载网络或本地资源;
  • 可以转换为自己需要的request(Square公司开源的另一个网络支持库:retrofit支持转化json,protocol buffers).

1.picasso的简单使用

1 Picasso.with(context).load(url).placeholder(R.drawable.pic).error(R.drawable.pic).into(tagert);
需要注意:url为http链接时,load(url),当url为本地图片路径时load(new File(url)).

需要对图片简单处理:transform(Transformation);
如下是显示圆形图片
 
//重载函数
public Bitmap transform(Bitmap source) { int width = source.getWidth(); int height = source.getHeight(); int x = 0, y = 0; if (mSquareRound && width != height) { if (width < height) { y = (height - width)/2; } else { x = (width - height)/2; } width = height = Math.min(width, height); Bitmap tempSource = Bitmap.createBitmap(source, x, y, width, height); source.recycle(); source = tempSource; } Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Paint paint = new Paint(); paint.setDither(true); paint.setAntiAlias(true); BitmapShader shader = new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint.setShader(shader); Canvas canvas = new Canvas(output); final RectF bounds = new RectF(0, 0, width, height); canvas.drawOval(bounds, paint); source.recycle(); return output; }

transform(new RoundTransformation(true));

 

2.picasso的类图如下:

关键类的简单介绍:

Cache:缓存类,子类LruCache才采用Least Recently Used 近期最少使用算法,当然LinkedHashMap已实现这个策略,只需根据配置的缓存大小来trimToSize。

picass缓存策略单一,没有另一个图片下载缓存库 Android-universal-Image-Loader 缓存策略丰富:FIFOLimitedMemoryCache ,LimitedAgeMemoryCache 等

而本地文件缓存,picasso引用okhttp的文件缓存,而Android-universal-Image-Loader也不同几种文件缓存策略。

 

RequestCreator:Requst构建者,可以通过不同参数配置request请求。

Request:请求封装类,之后把所有对图形的操作都会记录在这里,供之后图形的创建使用,如重新计算大小,旋转角度,也可以自定义变换,只需要实现Transformation,一个bitmap转换的接口。传到另一个结构中Action。

Action:Action代表了一个具体的加载任务,主要用于图片加载后的结果回调,有两个抽象方法,complete和error.来通知上层。

BitmapHunter:一个runnable线程,网络下载工作线程,交给ExecutorServer管理执行。

Downloader:网络图片下载器,子类不同来选择http client。

RequestHandler:请求处理类,子类根据图片来源获取资源。

Dispathcer:任务调度器,调度和维护者actions 和 bitmapHunter,当bitmaphunter获取到图片时,会转给dispather,发送异步消息,最终会转到action.complete()或者action.error().

 

3.picasso.with(context).loar(http).into(imageview);流程图如下

 

网上找到一个一张很好的picasso流程分析图:http://www.happyhls.me/blog/2014/11/27/picasso%E6%BA%90%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%9A5%E3%80%81picasso%E6%9E%B6%E6%9E%84%E5%88%86%E6%9E%90/

 要点:

1在into(target).中做了是否在UI主线成操作,由于要显示默认的图片,得保证在主线程中对ui操作。

2.Dispather本质上可以看成一个线程,action提交和请求结果的回调都是在DispatcherThread线程中通过DispacherHandler处理。

3.picasso中通过广播监控网络状态,来动态改变PicassoExecutorService中线程数量。

4.picasso单例的思考:picasso构建时,初始化了cache,注册了监听网络状态的广播等,在调用shutDown()方法中做了cache清空和注销广播工作,但是,对于这个全局picasso在什么时机做清理工作了(显式调用shutdown()),这个时机不好把握,除非app能够自身监听application被关闭,回调shutdown.如果不显式调用shutdown,cache没有清空,广播就没有注销。对于context.registerReceiver(),context可能是application,可能是activity(在ams,在activity被destory过程会隐式调用unregisterReceiver()或unbindService()),对于context是application没有隐式注销unregisterReceiver(),可能存在潜在问题(内存泄露会不会出现了);如果想对每个activity拥有个picasso,则可以使用

Picasso.Builder(context).build();这样可以在每个activity中ondestory中显式调用picasso.shutdown();

5.BitmapHunt.hunt()中,,同一时刻,仅允许一张图片进行解码,加了同步安全,进行Transformation,防止oom.

 

4.使用picasso可能出现的问题:

1.图片有时会显示不了,查看应用中图片缓存文件,对一张图片,会生成两个文件:,.0文件保存了http响应相应的信息,.1文件时加密后的图片文件。.0文件的内容如下:

http://192.168.2.40:82/group1/M00/0A/60/wKgCKFQJQkKABEn9AAPhsEdiW-o.phpzqf
GET
0
HTTP/1.1 200 OK
9
Server: nginx/1.2.6
Date: Tue, 16 Sep 2014 12:02:26 GMT
Content-Length: 254384
Last-Modified: Fri, 05 Sep 2014 04:55:30 GMT
Connection: keep-alive
Accept-Ranges: bytes
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1410868547182
OkHttp-Received-Millis: 1410868547357

这边出现问题时,Content-Length: 0,但是图片确实存在。如果出现有时显示不了,可以从这方面查看下。可行的方法:

定制Downloader,配置缓存目录和缓存大小。

2.当picasso显示列表中大量图片时,查看大图时,有时还是会出现oom,除了对长宽比压缩,也可以以另外一个进程查看大图。

 

posted on 2014-12-02 16:10  toney.wu  阅读(3096)  评论(0编辑  收藏  举报

导航