0使用手册
http://square.github.io/picasso/
1使用方法简介
Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(imageView)
2 基本原理
先使用Picasso.Builder生成一个单例Picasso,load的时候生成一个RequestCreator,再设置不同的Reqeust参数,into的时候生成一个Request,再将Request和Target组合成Action,由Picasso交给Dispatcher后台执行,Dispatcher用Action生成BitmapHunter,交于PicassoExecutorService执行,BitmapHunter下载完成,执行相应的变换后,用Handler通知Dispatcher缓存在内存中,Dispatcher再用Handler通知Picasso调用Action.complete()方法
3数据结构分析
RequestHandler: 根据Request获取相应的内容。FileRequestHandler使用ContentResolver从文件中获取。NetworkRequestHandler使用Downloader从网络获取。ResourceRequestHandler从apk资源中获取。ContactsPhotoRequestHandler使用ContentResolver从通讯录中获取。ContentStreamRequestHandler使用ContentResolver获取。
Downloader: 从网络获取时需要下载。UrlConnectionDownloader使用UrlConnection从网络下载,HttpResponseCache可以让UrlConnection使用文件缓存数据。OkHttpDownloader使用OkHttp库来下载图片,OkHttpClient.setCache可以让OkHttp使用文件缓存
Stats:统计数据,缓存的命中率等等
Action:包含Request,Target和PlaceHolder,和异步加载后的回调,complete,error,cancel。
BitmapHunter: 异步Runnable任务。
4源代码分析
Picasso.Builder.build()
/**
2. 构造Picasso,使用Picasso.with会构造默认的方法,如果要自定义Picasso,则需要使用Builder,并在构造好了
3. 之后使用Picasso.setSingletonInstance.
*/
/** Create the {@link Picasso} instance. */
public Picasso
build() {
Context context =
this.context;
if (downloader ==
null) {
downloader = Utils.createDefaultDownloader(context);
}
if (cache ==
null) {
cache =
new LruCache(context);
}
if (service ==
null) {
service =
new PicassoExecutorService();
}
if (transformer ==
null) {
transformer = RequestTransformer.IDENTITY;
}
Stats stats =
new Stats(cache);
Dispatcher dispatcher =
new Dispatcher(context, service, HANDLER, downloader, cache, stats);
return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
}
12345678910111213141516171819202122232425262728
12345678910111213141516171819202122232425262728
RequestCreator.into()
/**
* 调用into方法时,使用Request.Builder创建一个Request,然后交给Dispatcher调度执行。
* @param target
*/
public void into(Target target) {
long started = System.nanoTime();
checkMain();
if (target ==
null) {
throw new IllegalArgumentException(
"Target must not be null.");
}
if (deferred) {
throw new IllegalStateException(
"Fit cannot be used with a Target.");
}
if (!data.hasImage()) {
picasso.cancelRequest(target);
target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() :
null);
return;
}
Request request = createRequest(started);
String requestKey = createKey(request);
if (shouldReadFromMemoryCache(memoryPolicy)) {
Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
if (bitmap !=
null) {
picasso.cancelRequest(target);
target.onBitmapLoaded(bitmap, MEMORY);
return;
}
}
target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() :
null);
Action action =
new TargetAction(picasso, target, request, memoryPolicy, networkPolicy, errorDrawable,
requestKey, tag, errorResId);
picasso.enqueueAndSubmit(action);
}
123456789101112131415161718192021222324252627282930313233343536373839404142
123456789101112131415161718192021222324252627282930313233343536373839404142
BitmapHunter.hunt()
Bitmap hunt() throws IOException {
Bitmap bitmap
= null;
if (shouldReadFromMemoryCache(memoryPolicy)) {
bitmap
= cache.get(key);
if (bitmap
!= null) {
stats
.dispatchCacheHit();
loadedFrom
= MEMORY;
if (picasso
.loggingEnabled) {
log(OWNER_HUNTER, VERB_DECODED,
data.logId(),
"from cache");
}
return bitmap;
}
}
data.networkPolicy
= retryCount
== 0 ? NetworkPolicy
.OFFLINE
.index : networkPolicy;
RequestHandler
.Result result
= requestHandler
.load(
data, networkPolicy);
if (result
!= null) {
loadedFrom
= result
.getLoadedFrom();
exifRotation
= result
.getExifOrientation();
bitmap
= result
.getBitmap();
if (bitmap
== null) {
InputStream is
= result
.getStream();
try {
bitmap
= decodeStream(is,
data);
} finally {
Utils
.closeQuietly(is);
}
}
}
if (bitmap
!= null) {
if (picasso
.loggingEnabled) {
log(OWNER_HUNTER, VERB_DECODED,
data.logId());
}
stats
.dispatchBitmapDecoded(bitmap);
if (
data.needsTransformation()
|| exifRotation
!= 0) {
synchronized (DECODE_LOCK) {
if (
data.needsMatrixTransform()
|| exifRotation
!= 0) {
bitmap
= transformResult(
data, bitmap, exifRotation);
if (picasso
.loggingEnabled) {
log(OWNER_HUNTER, VERB_TRANSFORMED,
data.logId());
}
}
if (
data.hasCustomTransformations()) {
bitmap
= applyCustomTransformations(
data.transformations, bitmap);
if (picasso
.loggingEnabled) {
log(OWNER_HUNTER, VERB_TRANSFORMED,
data.logId(),
"from custom transformations");
}
}
}
if (bitmap
!= null) {
stats
.dispatchBitmapTransformed(bitmap);
}
}
}
return bitmap;
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
Dispatcher.performComplete()
//先判断是否要写内存缓存,然后将当前的hunter批量。
//批量的原因是在Picasso的Handler当前可能还有没有处理的。再Dispatcher这一级别再缓冲一下
void performComplete(BitmapHunter hunter) {
if (shouldWriteToMemoryCache(hunter
.getMemoryPolicy())) {
cache
.set(hunter
.getKey(), hunter
.getResult())
}
hunterMap
.remove(hunter
.getKey())
batch(hunter)
if (hunter
.getPicasso()
.loggingEnabled) {
log(OWNER_DISPATCHER, VERB_BATCHED, getLogIdsForHunter(hunter),
"for completion")
}
}
123456789101112
123456789101112
Picasso.comple()
void complete(BitmapHunter hunter) {
Action single = hunter.getAction();
List<Action> joined = hunter.getActions();
boolean hasMultiple = joined !=
null && !joined.isEmpty();
boolean shouldDeliver = single !=
null || hasMultiple;
if (!shouldDeliver) {
return;
}
Uri uri = hunter.getData().uri;
Exception exception = hunter.getException();
Bitmap result = hunter.getResult();
LoadedFrom
from = hunter.getLoadedFrom();
if (single !=
null) {
deliverAction(result,
from, single);
}
if (hasMultiple) {
for (
int i =
0, n = joined.size(); i < n; i++) {
Action
join = joined.
get(i);
deliverAction(result,
from,
join);
}
}
if (listener !=
null && exception !=
null) {
listener.onImageLoadFailed(
this, uri, exception);
}
}
123456789101112131415161718192021222324252627282930313233
123456789101112131415161718192021222324252627282930313233