目录
一、Picasso使用
二、Picasso初始化
三、Picasso配置
四、Picasso发送请求和缓存
五、Picasso对远程图片数据处理
六、总结
一 Picasso使用
Picasso.get().load(uri).into(iv_image);
二 Picasso初始化
Picasso.get() 会初始化一个Picasso单例对象
2.1 双检测单例
Picasso.java
public static Picasso get() {
//使用双检测机制保证
if (singleton == null) {
synchronized (Picasso.class) {
if (singleton == null) {
//初始化从context 使用的是ContentProvider
if (PicassoProvider.context == null) {
throw new IllegalStateException("context == null");
}
//创建Picasso对象
singleton = new Builder(PicassoProvider.context).build();
}
}
}
return singleton;
}
2.2 ContentProvider初始化context
PicassoProvider.java
@RestrictTo(LIBRARY)
public final class PicassoProvider extends ContentProvider {
@SuppressLint("StaticFieldLeak") static Context context;
@Override public boolean onCreate() {
context = getContext();
return true;
}
···
}
2.3 创建Picasso对象
singleton = new Builder(PicassoProvider.context).build(); 创建Builder对象
Picasso.Builder.java
public Builder(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("Context must not be null.");
}
this.context = context.getApplicationContext();
}
建造者模式创建Picasso对象
Picasso.Builder.java
public Picasso build() {
Context context = this.context;
if (downloader == null) {
//创建OkHttp3的下载器
downloader = new OkHttp3Downloader(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);
//构造Picasso对象
return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
}
Picasso对象初始化
Picasso.java
Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
RequestTransformer requestTransformer, List<RequestHandler> extraRequestHandlers, Stats stats,
Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled) {
this.context = context;
this.dispatcher = dispatcher;
this.cache = cache;
this.listener = listener;
this.requestTransformer = requestTransformer;
this.defaultBitmapConfig = defaultBitmapConfig;
int builtInHandlers = 7; // Adjust this as internal handlers are added or removed.
int extraCount = (extraRequestHandlers != null ? extraRequestHandlers.size() : 0);
List<RequestHandler> allRequestHandlers = new ArrayList<>(builtInHandlers + extraCount);
// ResourceRequestHandler needs to be the first in the list to avoid
// forcing other RequestHandlers to perform null checks on request.uri
// to cover the (request.resourceId != 0) case.
//责任链模式处理请求
allRequestHandlers.add(new ResourceRequestHandler(context));
if (extraRequestHandlers != null) {
allRequestHandlers.addAll(extraRequestHandlers);
}
allRequestHandlers.add(new ContactsPhotoRequestHandler(context));
allRequestHandlers.add(new MediaStoreRequestHandler(context));
allRequestHandlers.add(new ContentStreamRequestHandler(context));
allRequestHandlers.add(new AssetRequestHandler(context));
allRequestHandlers.add(new FileRequestHandler(context));
allRequestHandlers.add(new NetworkRequestHandler(dispatcher.downloader, stats));
requestHandlers = Collections.unmodifiableList(allRequestHandlers);
this.stats = stats;
this.targetToAction = new WeakHashMap<>();
this.targetToDeferredRequestCreator = new WeakHashMap<>();
this.indicatorsEnabled = indicatorsEnabled;
this.loggingEnabled = loggingEnabled;
this.referenceQueue = new ReferenceQueue<>();
this.cleanupThread = new CleanupThread(referenceQueue, HANDLER);
this.cleanupThread.start();
}
三 Picasso配置
Picasso.get().load(uri)会返回一个RequestCreator的对象,这个对象使用建造者模式配置请求参数,所有的load都是会返回RequestCreator,他是请求的配置中心,配置中心配置请求参数,比如占位图、缓存策略、转换。
Picasso.java
public RequestCreator load(@NonNull File file) {
if (file == null) {
//创建RequestCreator
return new RequestCreator(this, null, 0);
}
return load(Uri.fromFile(file));
}
四 Picasso发送请求和缓存
Picasso.get().load(uri).into(iv_image);开始请求图片数据,从缓存或者网络获取
4.1 发送请求
RequestCreator.java
public void into(ImageView target) {
into(target, null);
}
RequestCreator.java
public void into(ImageView target, Callback callback) {
long started = System.nanoTime();
//检测是否在主线程调用、如果不是在主线程抛出异常
checkMain();
//目标不能为null
if (target == null) {
throw new IllegalArgumentException("Target must not be null.");
}
//如果已经有图片了取消去请求
if (!data.hasImage()) {
picasso.cancelRequest(target);
//如果设置了占位符,设置占位符
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
return;
}
//自适应大小,创建延迟请求
if (deferred) {
//自适应不能设置大小
if (data.hasSize()) {
throw new IllegalStateException("Fit cannot be used with resize.");
}
int width = target.getWidth();
int height = target.getHeight();
if (width == 0 || height == 0) {
//加载占位图
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
//放入请求缓存中
picasso.defer(target, new DeferredRequestCreator(this, target, callback));
return;
}
data.resize(width, height);
}
//创建请求
Request request = createRequest(started);
//获取请求的key
String requestKey = createKey(request);
//如果从内存缓存中读取数据那直接从内存缓存中读取
if (shouldReadFromMemoryCache(memoryPolicy)) {
//从内存缓存中获取数据
Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
if (bitmap != null) {
//获取到数据取消请求
picasso.cancelRequest(target);
//设置bitmap
setBitmap(target, picasso.context, bitmap, MEMORY, noFade, picasso.indicatorsEnabled);
···
//如果设置了回调调用回调
if (callback != null) {
callback.onSuccess();
}
return;
}
}
//设置占位图
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
//创建请求的Action
Action action =
new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
errorDrawable, requestKey, tag, callback, noFade);
//添加并提交到队列
picasso.enqueueAndSubmit(action);
}
4.2 自适应测量控件大小并发送延迟请求
如果我们的target是ImageView并且设置了fit(),会先去测量view宽高,在获取宽高后延迟请求
RequestCreator.java
public RequestCreator fit() {
deferred = true;
return this;
}
RequestCreator.java
public void into(ImageView target, Callback callback) {
long started = System.nanoTime();
····
//自适应大小,创建延迟请求
if (deferred) {
//自适应不能设置大小
if (data.hasSize()) {
throw new IllegalStateException("Fit cannot be used with resize.");
}
int width = target.getWidth();
int height = target.getHeight();
if (width == 0 || height == 0) {
//加载占位图
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
//放入请求缓存中
picasso.defer(target, new DeferredRequestCreator(this, target, callback));
return;
}
data.resize(width, height);
}
····
}
延迟请求创建new DeferredRequestCreator(this, target, callback),它实现了OnPreDrawListener,在view绘制的时候获取到view的宽度和高度,也实现了OnAttachStateChangeListener在view attach到View树上时注册OnPreDrawListener,detach时将OnPreDrawListener移除
DeferredRequestCreator.java
DeferredRequestCreator(RequestCreator creator, ImageView target, Callback callback) {
this.creator = creator;
/弱引用引用target
this.target = new WeakReference<>(target);
this.callback = callback;
//添加监听view attach状态
target.addOnAttachStateChangeListener(this);
// Only add the pre-draw listener if the view is already attached.
// See: https://github.com/square/picasso/issues/1321
//如果target已经添加到view上,直接调用attach回调
if (target.getWindowToken() != null) {
onViewAttachedToWindow(target);
}
}
view绘制完成回调OnPreDrawListener的onPreDraw()方法
DeferredRequestCreator.java
@Override public boolean onPreDraw() {
//获取target
ImageView target = this.target.get();
if (target == null) {
return true;
}
ViewTreeObserver vto = target.getViewTreeObserver();
//如果View没有显示直接返回
if (!vto.isAlive()) {
return true;
}
//获取目标宽高
int width = target.getWidth();
int height = target.getHeight();
//如果没有获取到返回
if (width <= 0 || height <= 0) {
return true;
}
//移除监听
target.removeOnAttachStateChangeListener(this);
vto.removeOnPreDrawListener(this);
this.target.clear();
//从新赋值宽高,然后调用into从新请求图片数据
this.creator.unfit().resize(width, height).into(target, callback);
return true;
}
4.3 创建图片请求
Request request = createRequest(started);使用建造者模式创建请求
RequestCreator.java
public void into(ImageView target, Callback callback) {
long started = System.nanoTime();
···
Request request = createRequest(started);
···
}
RequestCreator.java
private Request createRequest(long started) {
//请求id,使用的是tomicInteger保证线程安全
int id = nextId.getAndIncrement();
Request request = data.build();
request.id = id;
request.started = started;
···
//可以在外部设置对请求进行转换
Request transformed = picasso.transformRequest(request);
if (transformed != request) {
// If the request was changed, copy over the id and timestamp from the original.
transformed.id = id;
transformed.started = started;
···
}
return transformed;
}
picasso.transformRequest(request);是对请求做转换或者是提供请求监听的切点
Request transformRequest(Request request) {
Request transformed = requestTransformer.transformRequest(request);
···
return transformed;
}
requestTransformer可以在创建Picasso的时候设置
Picasso.java
public Picasso build() {
···
if (transformer == null) {
transformer = RequestTransformer.IDENTITY;
}
····
return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
}
4.4 从内存中读取数据
shouldReadFromMemoryCache(memoryPolicy)如果读取策略配置了可从内存中读取数据,那开始从内存中读取数据,使用之前创建的key从LRUCache中读取picasso.quickMemoryCacheCheck(requestKey);
public void into(ImageView target, Callback callback) {
···
if (shouldReadFromMemoryCache(memoryPolicy)) {
Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
//取消请求,设置图片,调用回调
if (bitmap != null) {
picasso.cancelRequest(target);
setBitmap(target, picasso.context, bitmap, MEMORY, noFade, picasso.indicatorsEnabled);
···
if (callback != null) {
callback.onSuccess();
}
return;
}
}
···
}
从缓存中获取数据,如果命中,走命中分发流程,如果没有命中走未命中流程
Picasso.java
Bitmap quickMemoryCacheCheck(String key) {
Bitmap cached = cache.get(key);
if (cached != null) {
stats.dispatchCacheHit();
} else {
stats.dispatchCacheMiss();
}
return cached;
}
4.4.1 缓存命中和未命中
stats内部封装了HandlerThread,dispatchCacheHit(),dispatchCacheMiss()就是往子线程里发送数据
Stats.java
void dispatchCacheHit() {
handler.sendEmptyMessage(CACHE_HIT);
}
void dispatchCacheMiss() {
handler.sendEmptyMessage(CACHE_MISS);
}
消息的处理
Stats.StatsHandler.java
@Override public void handleMessage(final Message msg) {
switch (msg.what) {
case CACHE_HIT:
stats.performCacheHit();
break;
case CACHE_MISS:
stats.performCacheMiss();
break;
···
}
}
命中和未命中只是简单的执行了+1操作,用于oom快照使用
void performCacheHit() {
cacheHits++;
}
void performCacheMiss() {
cacheMisses++;
}
4.5 从网络或者文件中获取图片
RequestCreator.java
public void into(ImageView target, Callback callback) {
···
//设置占位图
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
//创建请求的Action
Action action =
new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
errorDrawable, requestKey, tag, callback, noFade);
//添加到请求队列
picasso.enqueueAndSubmit(action);
}
Picasso.java
void enqueueAndSubmit(Action action) {
Object target = action.getTarget();
if (target != null && targetToAction.get(target) != action) {
// This will also check we are on the main thread.
cancelExistingRequest(target);
targetToAction.put(target, action);
}
submit(action);
}
void submit(Action action) {
dispatcher.dispatchSubmit(action);
}
dispatcher负责任务分发,是在创建Picasso的时候赋值的
Picasso.java
public Picasso build() {
···
Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);
return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
}
dispatcher.dispatchSubmit(action);调用Handler向DispatcherThread发送消息,DispatcherThread是HandlerThread
Dispatcher.java
void dispatchSubmit(Action action) {
handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action));
}
消息的处理
Dispatcher.DispatcherHandler.java
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case REQUEST_SUBMIT: {
Action action = (Action) msg.obj;
dispatcher.performSubmit(action);
break;
}
····
}
}
Dispatcher.java
void performSubmit(Action action) {
performSubmit(action, true);
}
void performSubmit(Action action, boolean dismissFailed) {
if (pausedTags.contains(action.getTag())) {
//添加到暂停列表
pausedActions.put(action.getTarget(), action);
···
return;
}
//这里是真正封装请求调用的Runnable
BitmapHunter hunter = hunterMap.get(action.getKey());
if (hunter != null) {
//关联request并设置优先级
hunter.attach(action);
return;
}
//如果线程池停止服务了返回
if (service.isShutdown()) {
···
return;
}
//创建处理请求
hunter = forRequest(action.getPicasso(), this, cache, stats, action);
//提交任务到线程池中
hunter.future = service.submit(hunter);
hunterMap.put(action.getKey(), hunter);
if (dismissFailed) {
failedActions.remove(action.getTarget());
}
···
}
创建请求、 picasso.getRequestHandlers();存储了所有能处理图片请求的策略,requestHandler.canHandleRequest(request)检测是否能处理当前的图片请求,如果能处理返回,如果不能处理创建默认BitmapHunter
BitmapHunter.java
static BitmapHunter forRequest(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats,
Action action) {
Request request = action.getRequest();
List<RequestHandler> requestHandlers = picasso.getRequestHandlers();
// Index-based loop to avoid allocating an iterator.
//noinspection ForLoopReplaceableByForEach
for (int i = 0, count = requestHandlers.size(); i < count; i++) {
RequestHandler requestHandler = requestHandlers.get(i);
if (requestHandler.canHandleRequest(request)) {
return new BitmapHunter(picasso, dispatcher, cache, stats, action, requestHandler);
}
}
return new BitmapHunter(picasso, dispatcher, cache, stats, action, ERRORING_HANDLER);
}
图片请求策略赋值是在创建Picasso的时候
Picasso.java
Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
RequestTransformer requestTransformer, List<RequestHandler> extraRequestHandlers, Stats stats,
Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled) {
···
allRequestHandlers.add(new ResourceRequestHandler(context));
if (extraRequestHandlers != null) {
allRequestHandlers.addAll(extraRequestHandlers);
}
allRequestHandlers.add(new ContactsPhotoRequestHandler(context));
allRequestHandlers.add(new MediaStoreRequestHandler(context));
allRequestHandlers.add(new ContentStreamRequestHandler(context));
allRequestHandlers.add(new AssetRequestHandler(context));
allRequestHandlers.add(new FileRequestHandler(context));
allRequestHandlers.add(new NetworkRequestHandler(dispatcher.downloader, stats));
····
}
创建BitmapHunter后返回到Dispatcher中的performSubmit()方法然后将任务提交到线程池中hunter.future = service.submit(hunter);service是在创建Picasso对象时赋值的类型为PicassoExecutorService,默认线程数为3个,最大线程数也为3个,使用的是优先阻塞队列,创建线程工厂为后台线程,提交获取任务后会执行BitmapHunter的run方法
BitmapHunter.java
@Override public void run() {
try {
//更新线程名称
updateThreadName(data)
···
//获取结果
result = hunt();
// 分发数据
if (result == null) {
dispatcher.dispatchFailed(this);
} else {
dispatcher.dispatchComplete(this);
}
} catch (NetworkRequestHandler.ResponseException e) {
if (!NetworkPolicy.isOfflineOnly(e.networkPolicy) || e.code != 504) {
exception = e;
}
dispatcher.dispatchFailed(this);
} catch (IOException e) {
exception = e;
dispatcher.dispatchRetry(this);
} catch (OutOfMemoryError e) {
StringWriter writer = new StringWriter();
stats.createSnapshot().dump(new PrintWriter(writer));
exception = new RuntimeException(writer.toString(), e);
dispatcher.dispatchFailed(this);
} catch (Exception e) {
exception = e;
dispatcher.dispatchFailed(this);
} finally {
Thread.currentThread().setName(Utils.THREAD_IDLE_NAME);
}
}
BitmapHunter.java
Bitmap hunt() throws IOException {
Bitmap bitmap = null;
//内存中加载
if (shouldReadFromMemoryCache(memoryPolicy)) {
bitmap = cache.get(key);
if (bitmap != null) {
stats.dispatchCacheHit();
loadedFrom = MEMORY;
···
return bitmap;
}
}
networkPolicy = retryCount == 0 ? NetworkPolicy.OFFLINE.index : networkPolicy;
//根据策略加载数据
RequestHandler.Result result = requestHandler.load(data, networkPolicy);
···
return bitmap;
}
4.5.1 从文件中获取图片
使用的是FileRequestHandler,调用okio处理图片数据
class FileRequestHandler extends ContentStreamRequestHandler {
···
@Override public Result load(Request request, int networkPolicy) throws IOException {
Source source = Okio.source(getInputStream(request));
return new Result(null, source, DISK, getFileExifRotation(request.uri));
}
static int getFileExifRotation(Uri uri) throws IOException {
ExifInterface exifInterface = new ExifInterface(uri.getPath());
return exifInterface.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
}
}
4.5.2 从网络中获取图片
NetworkRequestHandler使用OKhttp3获取网络图片
NetworkRequestHandler.java
@Override public Result load(Request request, int networkPolicy) throws IOException {
okhttp3.Request downloaderRequest = createRequest(request, networkPolicy);
Response response = downloader.load(downloaderRequest);
ResponseBody body = response.body();
if (!response.isSuccessful()) {
body.close();
throw new ResponseException(response.code(), request.networkPolicy);
}
// Cache response is only null when the response comes fully from the network. Both completely
// cached and conditionally cached responses will have a non-null cache response.
Picasso.LoadedFrom loadedFrom = response.cacheResponse() == null ? NETWORK : DISK;
// Sometimes response content length is zero when requests are being replayed. Haven't found
// root cause to this but retrying the request seems safe to do so.
if (loadedFrom == DISK && body.contentLength() == 0) {
body.close();
throw new ContentLengthException("Received response with 0 content-length header.");
}
if (loadedFrom == NETWORK && body.contentLength() > 0) {
stats.dispatchDownloadFinished(body.contentLength());
}
return new Result(body.source(), loadedFrom);
}
五 Picasso对远程图片数据处理
无论是从网络函数从文件中获取图片数据,最后都是返回一个Result的对象,然后开始解码创建Bitmap
BitmapHunter.java
Bitmap hunt() throws IOException {
···
//根据策略加载数据
RequestHandler.Result result = requestHandler.load(data, networkPolicy);
if (result != null) {
//获取bitmap
loadedFrom = result.getLoadedFrom();
exifOrientation = result.getExifOrientation();
bitmap = result.getBitmap();
// If there was no Bitmap then we need to decode it from the stream.
if (bitmap == null) {
Source source = result.getSource();
try {
bitmap = decodeStream(source, data);
} finally {
try {
//noinspection ConstantConditions If bitmap is null then source is guranteed non-null.
source.close();
} catch (IOException ignored) {
}
}
}
}
if (bitmap != null) {
//分发解码
stats.dispatchBitmapDecoded(bitmap);
if (data.needsTransformation() || exifOrientation != 0) {
//加锁
synchronized (DECODE_LOCK) {
if (data.needsMatrixTransform() || exifOrientation != 0) {
//如target宽高不为0,或者是需要旋转,那么开始进行变换
bitmap = transformResult(data, bitmap, exifOrientation);
···
}
//定义了转换开始转换
if (data.hasCustomTransformations()) {
bitmap = applyCustomTransformations(data.transformations, bitmap);
···
}
}
}
if (bitmap != null) {
//通知变换完成
stats.dispatchBitmapTransformed(bitmap);
}
}
}
return bitmap;
}
处理完图片转换回到BitmapHunter的run方法
BitmapHunter.java
@Override public void run() {
try {
updateThreadName(data);
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_EXECUTING, getLogIdsForHunter(this));
}
result = hunt();
//这里开始分发处理完的图片数据
if (result == null) {
dispatcher.dispatchFailed(this);
} else {
dispatcher.dispatchComplete(this);
}
···
}
Dispatcher.java
void dispatchComplete(BitmapHunter hunter) {
handler.sendMessage(handler.obtainMessage(HUNTER_COMPLETE, hunter));
}
Dispatcher.DispatcherHandler.java
@Override public void handleMessage(final Message msg) {
switch (msg.what) {
···
case HUNTER_COMPLETE: {
BitmapHunter hunter = (BitmapHunter) msg.obj;
dispatcher.performComplete(hunter);
break;
}
···
}
}
Dispatcher.java
void performComplete(BitmapHunter hunter) {
//设置到内存缓存
if (shouldWriteToMemoryCache(hunter.getMemoryPolicy())) {
cache.set(hunter.getKey(), hunter.getResult());
}
//清理工作
hunterMap.remove(hunter.getKey());
batch(hunter);
···
}
}
private void batch(BitmapHunter hunter) {
if (hunter.isCancelled()) {
return;
}
if (hunter.result != null) {
//清空bitmap缓存
hunter.result.prepareToDraw();
}
batch.add(hunter);
/发送消息处理图片
if (!handler.hasMessages(HUNTER_DELAY_NEXT_BATCH)) {
handler.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY);
}
}
Dispatcher.DispatcherHandler.java
@Override public void handleMessage(final Message msg) {
switch (msg.what) {
···
case HUNTER_DELAY_NEXT_BATCH: {
dispatcher.performBatchComplete();
break;
}
···
}
}
Dispatcher.java
void performBatchComplete() {
List<BitmapHunter> copy = new ArrayList<>(batch);
batch.clear();
//切换到主线程处理 mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy));
//打点
logBatch(copy);
}
mainThreadHandler创建Dispatcher的时候传入的参数,是Picasso的一个成员变量
Picasso.java
static final Handler HANDLER = new Handler(Looper.getMainLooper()) {
@Override public void handleMessage(Message msg) {
switch (msg.what) {
case HUNTER_BATCH_COMPLETE: {
@SuppressWarnings("unchecked") List<BitmapHunter> batch = (List<BitmapHunter>) msg.obj;
//noinspection ForLoopReplaceableByForEach
//通知处理
for (int i = 0, n = batch.size(); i < n; i++) {
BitmapHunter hunter = batch.get(i);
hunter.picasso.complete(hunter);
}
break;
}
····
}
}
};
Picasso.java
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, exception);
}
if (hasMultiple) {
//noinspection ForLoopReplaceableByForEach
for (int i = 0, n = joined.size(); i < n; i++) {
Action join = joined.get(i);
deliverAction(result, from, join, exception);
}
}
//通知加载完成
if (listener != null && exception != null) {
listener.onImageLoadFailed(this, uri, exception);
}
}
Picasso.java
private void deliverAction(Bitmap result, LoadedFrom from, Action action, Exception e) {
if (action.isCancelled()) {
return;
}
if (!action.willReplay()) {
targetToAction.remove(action.getTarget());
}
if (result != null) {
···
//通知回调
action.complete(result, from);
···
} else {
action.error(e);
···
}
}
这个action就是在RequestCenter的int()方法创建的Action
RequestCenter.java
public void into(ImageView target, Callback callback) {
···
Action action =
new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
errorDrawable, requestKey, tag, callback, noFade);
picasso.enqueueAndSubmit(action);
}
ImageViewAction.java
@Override public void complete(Bitmap result, Picasso.LoadedFrom from) {
if (result == null) {
throw new AssertionError(
String.format("Attempted to complete action with no result!\n%s", this));
}
ImageView target = this.target.get();
if (target == null) {
return;
}
Context context = picasso.context;
boolean indicatorsEnabled = picasso.indicatorsEnabled;
//想target设置图片
PicassoDrawable.setBitmap(target, context, result, from, noFade, indicatorsEnabled);
if (callback != null) {
callback.onSuccess();
}
}
PicassoDrawable.java
static void setBitmap(ImageView target, Context context, Bitmap bitmap,
Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) {
Drawable placeholder = target.getDrawable();
if (placeholder instanceof Animatable) {
((Animatable) placeholder).stop();
}
PicassoDrawable drawable =
new PicassoDrawable(context, bitmap, placeholder, loadedFrom, noFade, debugging);
target.setImageDrawable(drawable);
}
六 总结
1 单例获取Picasso对象,调用load创建RequestCenter配置请求参数,并没有做Glide对控件生命周期的监控
2 调用into() 获取图片数据,它并没有Glide的两层内存缓存(当前活动的,和在内存中的),只有一种在内存中的缓存
3 磁盘的缓存也不像Glide的磁盘做细粒度的包含宽高的缓存,只是做了磁盘的普通缓存
杨说:Glide 4.11.0 生命周期监听
杨说:Glide 4.11.0 配置请求参数
杨说:Glide 4.11.0 发送请求准备工作
杨说:Glide 4.11.0 发送请求和缓存