1.Picasso load(参数)方法详解。
url,文件的path路径,资源id...
最终都会返回一个RequestCreator对象(图片加载请求)。
// Picasso.java
public RequestCreator load(String path) {
if(path == null){
return new RequestCreator(this, (Uri)null, 0);
} else if(path.trim().length() ==0) {
throw new IllegalArgumentException("Path must not be empty.");
} else {
return this.load(Uri.parse(path));
}
}
2.Picasso into(iv)方法详解。正式加载图片。
//RequestCreator.java
public void into(ImageView targetr){
this.into(target, (Callback)null);//2.1
}
//2.1
public void into(ImageView target,Callback callback){
long started = System.nanoTime();
Utils.checkMain();
if(target ==null){
throw new IllegalArgumentException("Target must not be null.");
} else if(!this.data.hasImage()){ //uri或资源id 非空
this.picasso.cancelRequest(target);//2.2 取消图片请求
if(this.setPlaceholder){ //设置占位符
PicassoDrawable.setPlaceholder(target, this.getPlaceholderDrawable());
}
} else {
if(this.deferred){ // 是否延迟加载
if(this.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);
}
// 这里主要是如果之前自定义了transform,会发生在这个方法(之前说过我们为您一般也不需要定义这个东西)
Request request = createRequest(started);
// 这里其实主要是将request和key关联,和我们之前说key可以理解为标识就有了联系
String requestKey = createKey(request);
// 是否在内存缓存中读取数据
if (shouldReadFromMemoryCache(memoryPolicy)) {
// 从缓存中获取bitmap
Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
if (bitmap != null) {
// 取到bitmap,就把网络请求撤销。【重点方法】
picasso.cancelRequest(target);
setBitmap(target, picasso.context, bitmap, MEMORY, noFade, picasso.indicatorsEnabled);
if (picasso.loggingEnabled) {
log(OWNER_MAIN, VERB_COMPLETED, request.plainId(), "from " + MEMORY);
}
// 成功回调这个方法,在基本使用中我们是使用过的
if (callback != null) {
callback.onSuccess(); //成功加载图片的回调方法
}
return;
}
}
// 设置占位图
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
Action action =
new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
errorDrawable, requestKey, tag, callback, noFade);
// 最后开始提交任务
picasso.enqueueAndSubmit(action);
}
}
boolean hasImage() {
return this.url!=null || this.resourceId !=0;
}
// 2.2.1
public void cancelRequest(ImageView view){
this.cancelExistingRequest(view); // 2.2.2
}
// 2.2.3
private void cancelExistingRequest(Object target){
Utils.checkMain();
//Action 是request的包装类。里面有Picasso和Request等。
//其中包含了很多的其他东西,比如缓存策略,Picasso对象,
Action action = (Action)this.targetToAction.remove(target);
if(action != null){
action.cancel();
this.dispatcher.dispatchCancel(action);//2.2.4取消请求
}
if(target instanceof ImageView){
ImageView targetImageView=(ImageView)target;
//DeferredRequestCreator 是RequestCreator的包装类,是为了对ImageView的监听,
//跟进去,会发现getViewTreeObserver来监听,获取如具体的宽高等,因此也需要移除。
DeferredRequestCreator deferredRequestCreator = (DeferredRequestCreator)this
.targetToDeferredRequestCreator.remove(targetImageView);
if(deferredRequestCreator != null){
deferredRequestCreator.cancel();
}
}
}
//Dispatcher
//2.2.4
void dispatchCancel(Action action) {
this.handler.sendMessage(this.handler.obtainMessage(2,action)); //2.2.5
}
//Dispatcher.DispatchHandler. handleMessage(msg)
public void handleMessage(Message msg){
//...
case 2: //2.2.5
info3 = (Action)msg.obj;
this.dispatcher.performCancel(info3); //2.2.6
break;
}
//2.2.6
void performCancel(Action action) {
String key = action.getKey();
//2.2.7【核心类】可开启线程下载;可解码处理bitmap;可做图片旋转工作;是一个开启子线程的工具
BitmapHunter hunter = (BitmapHunter)this.hunterMap.get(key);
//....
if(hunter!=null) {}
if(this.pauseTags.contains(action.getTag())){}
}
//2.2.7 BitmapHunter实现了Runnable接口,我们要关注的是他的run方法
@Override public void run() {
try {
updateThreadName(data);//修改线程名称
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_EXECUTING, getLogIdsForHunter(this));
}
// 获取图片(首先通过内存,不行在通过网络,用okhttp3)
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);
}
}
Action.java
createRequest
private Request createRequest(long started){//创建加载图片的请求
Request request = this.data.build();
Request transformed = this.picasso.transformRequest(request);
}
//ImageViewAction.java
class ImageViewAction extends Action<ImageView>{
ImageViewAction(Picasso picasso,ImageView imageView,Request data,int memoryPolicy, ...){
super(picasso,imageView,data,memoryPolicy,networkPolicy,errorResId,errorDrawable,key...);
this.callback=callback;
}
}
//Action.java
Action(Picasso picasso,T target,Request,...){
this.target = target==? null: new Action.RequestWeakReference(this,target,...)
}
//enqueueAndSubmit
void enqueueAndSubmit(Action action) {
// 获取请求操作的对象
Object target = action.getTarget();
// 判断object和action是否匹配(这个object可以是ImageView,而action又是
//request的包装类,这一下,两者的结合就比较明白了(请求操作对象和具体的请求)
if (target != null && targetToAction.get(target) != action) {
// This will also check we are on the main thread.
// 发现不匹配,取消请求
cancelExistingRequest(target);
// 将此时两者关联(也就是放在一个map集合当中),缓存以备复用
targetToAction.put(target, action);
}
// 继续任务提交
submit(action);
}
void submit(Action action){
this.dispatcher.dispatchSubmit(action);
}
void dispatchSubmit(Action action){
this.handler.sendMessage(this.handler.obtainMessage(1, action));
}
//Dispatcher.DispatchHandler. handleMessage(msg)
public void handleMessage(Message msg){
//...
case 1:
info3 = (Action)msg.obj;
this.dispatcher.performSubmit(info3);
break;
}
void performSubmit(Action action){
this.performSubmit(action, true);
}
void performSubmit(Action action, boolean dismissFailed) {
// 判断是否延迟暂停加载(就是之前是否设置过暂停延迟的标记)
if (pausedTags.contains(action.getTag())) {
// 同样将target和action关联(此时存放发延迟加载),存放以便于后来的唤醒请求
pausedActions.put(action.getTarget(), action);
if (action.getPicasso().loggingEnabled) {
log(OWNER_DISPATCHER, VERB_PAUSED, action.request.logId(),"because tag '" + action.getTag() + "' is paused");
}
return;
}
// 获取请求的图片捕获器(就是一个runnable,说过,key可以当成bitmap和请求的标记)
BitmapHunter hunter = hunterMap.get(action.getKey());
if (hunter != null) {
// 这里是对hunter的action初始化并进行健壮性判断
hunter.attach(action);
return;
}
// 判断当前线程池是否关闭
if (service.isShutdown()) {
// 如果关闭,打印日志,直接结束
if (action.getPicasso().loggingEnabled) {
log(OWNER_DISPATCHER, VERB_IGNORED, action.request.logId(), "because shut down");
}
return;
}
// 未关闭:这个方法主要是找到能够处理相应请求request的requestHandler,并封装成BitmapHuntere返回
hunter = forRequest(action.getPicasso(), this, cache, stats, action);
// ****** 交给线程池service处理(获取图片),关注BitmapHunter的run方法(之前讲过了),future保存结果
hunter.future = service.submit(hunter);
// 关联,将key和hunter关联
hunterMap.put(action.getKey(), hunter);
if (dismissFailed) {
failedActions.remove(action.getTarget());
}
if (action.getPicasso().loggingEnabled) {
log(OWNER_DISPATCHER, VERB_ENQUEUED, action.request.logId());
}
}
//PicassoExecutorService.java
public Future<?> submit(Runnable task){
//PicassoFutureTask 便于控制处理的线程
PicassoExecutorService.PicassoFutureTask ftask = new PicassoExecutorService.PicassoFutureTask();
this.execute(ftask); //开启线程
return ftask;
}
static BitmapHunter forRequest(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats, Action action) {
Request request = action.getRequest();
List<RequestHandler> requestHandlers = picasso.getRequestHandlers();
// 此函数的核心在于这里,根据request的不同,选择匹配的requesthandler
// 所有的requesthandler都继承抽象类requestHandler,其中的核心方法是load
// 根据不同的图片来源选择不同的加载方式,比如assets文件夹中的图片和网络图片的加载方式肯定不一样
// 加载网络图片用的是NetworkRequestHandler
// 对于这个请求不确定性和多个处理器都有机会处理的请情况,可以看做是责任连模式的简单应用
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);
}
void attach(Action){
//...
this.actions.add(action); //加入List集合当中
//更新优先级
this.priority = actionPriority;
}
3.线程池在哪里执行。
//PicassoExecutorService.java
private static final class PicassoFutureTask extends FutureTask<BitmapHunter> implements ***
{
private final BitmapHunter hunter;
public PicassoFutureTask(BitmapHunter hunter) {
super(hunter, (Object)null);
this.hunter=hunter;
}
}
//【重点方法】
Result hunt() throws IOException {
//是否是内存模式读取
if (shouldReadFromMemoryCache(data.memoryPolicy)) {
Bitmap bitmap = cache.get(key);
if (bitmap != null) {
stats.dispatchCacheHit();
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_DECODED, data.logId(), "from cache");
}
return new Result(bitmap, MEMORY);
}
}
//确认重连次数
if (retryCount == 0) {
data = data.newBuilder().networkPolicy(NetworkPolicy.OFFLINE).build();
}
final AtomicReference<Result> resultReference = new AtomicReference<>();
final AtomicReference<Throwable> exceptionReference = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
try {
//在本例中因为是网络请求,使用的是NetworkRequestHandler, 这是通过查看
//其中的load会得知使用的完全是okhttp的下载方法。
requestHandler.load(picasso, data, new RequestHandler.Callback() {
@Override public void onSuccess(@Nullable Result result) {
resultReference.set(result);
latch.countDown();
}
@Override public void onError(@NonNull Throwable t) {
exceptionReference.set(t);
latch.countDown();
}
});
latch.await();
} catch (InterruptedException ie) {
InterruptedIOException interruptedIoException = new InterruptedIOException();
interruptedIoException.initCause(ie);
throw interruptedIoException;
}
//如果出现异常。则抛出
Throwable throwable = exceptionReference.get();
if (throwable != null) {
if (throwable instanceof IOException) {
throw (IOException) throwable;
}
if (throwable instanceof Error) {
throw (Error) throwable;
}
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
throw new RuntimeException(throwable);
}
Result result = resultReference.get();
if (result.hasBitmap()) {
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_DECODED, data.logId());
}
Bitmap bitmap = result.getBitmap();
stats.dispatchBitmapDecoded(bitmap);
//根据需求对bitmap进行剪裁
int exifOrientation = result.getExifRotation();
if (data.needsTransformation() || exifOrientation != 0) {
if (data.needsMatrixTransform() || exifOrientation != 0) {
bitmap = transformResult(data, bitmap, exifOrientation);
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId());
}
}
//如果设置了transFrom那么进行变换。
result = new Result(bitmap, result.getLoadedFrom(), exifOrientation);
if (data.hasCustomTransformations()) {
result = applyCustomTransformations(data.transformations, result);
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId(),
"from custom transformations");
}
}
}
if (result.hasBitmap()) {
stats.dispatchBitmapTransformed(result.getBitmap());
}
}
return result;
}
void dispatchCacheHit(){
this.handler.sendEmptyMessage(0);
}
//Stats.StatsHandler StatsHandler()
case 0: this.stats.performCacheHit(); break;
// 缓存命中++
void performCacheHit(){
++ this.cacheHits;
}
//NetworkRequestHandler.java
public Result load(Request request,int networkPolicy) throws IOException{
//下载器加载
Response response = this.downloader.load(request.uri, request.networkPolicy);
if(response == null) return null;
else {
LoadedFrom loadedFrom = response.cached?LoadedFrom,DISK:LoadedFrom.NETWORK;
Bitmap bitmap=response.getBitmap();
if(bitmap!=null) return new Result(bitmap, loadedFrom);
else {
InputStream is=response.getInputStream();
if(is==null) return null;
else if(loadedFrom == LoadedFrom.DISK && response.getContentLength()== 0L){
Utils.closeQuietly(is);
throw new NetworkRequestHandler.ContentLegnthException("");
}
}
}
}
4. // Downloader.java 接口,
具体的实现 OkHttpDownloader, UrlConnectionDownloader 的区别。
4.1 OkHttpDownloader 的实现。
public Response load(URI uri, int networkPolicy)throws IOException {
CacheControl cadhecontrol=null;
if(networkPolicy!=0){
if(NetworkPolicy.isOffline0nly(networkPolicy)){
cacheControl=CacheControl.FORCE_CACHE;
}else{
Builder builder=new Builder();
if(!NetworkPolicy.shouldReadFromDiskCache(networkPolicy)){
builder.noCache();//非内存缓存读取数据
}
if(!NetworkPolicy.shouldwriteToDiskCache(networkPolicy)){
builder.nostore();//非硬盘缓存读取数据
}
cacheControl = builder.build();
}
}
com.squareup.okhttp.Request.Builder builder1 =(new com.squareup.okhttp.Request.Builder()).url(uri.toString());
if(cachecontrol != null) builder1.cachecontrol(cachecontrol);
//调用同步请求
com.squareup.okhttp.Response response = this.client.newCall(builder1.build()).execute();
int responseCode = response.code();
if(responseCode>=300) {
response.body().close();
throw new ResponseException(responseCode + " "+response.message());
}else {
boolean fromCache =response.cacheResponse() !=null;
ResponseBody responseBody =response.body();
return new Response(responseBody.byteStream(),fromCache, responseBody.contentLength());
}
}
4.2 UrlConnectionDownloader 的实现。
public Response load(Uri uri, int networkPolicy)throws IOException {
if(VERSION.SDK INT>= 14){installCacheIfNeeded(this.context);}
HttpURLConnection connection =this.openConnection(uri);
connection.setUseCaches(true);//开启缓存
if(networkPolicy!=0) {
String responseCode;
if(NetworkPolicy.isOfflineOnly(networkPolicy))
{
responseCode = "only-if-cached,max-age=2147483647";
}else
{
StringBuilder contentLength =(StringBuilder)CACHE_HEADER_BUILDER.get();
contentLength.setLength(0);
if(!NetworkPolicy.shouldReadFromDiskCache(networkPolicy)){
contentLength.append("no-cache");
}
if(!NetworkPolicy.shouldwriteToDiskCache(networkPolicy)){
if(contentLength.length()>0) {
contentLength.append(',');
}
contentLength.append("no-store");
}
responseCode= contentLength.toString();
}
connection.setRequestProperty("Cache-Control", responseCode);
}
int responseCode1 = connection.getResponseCode();
if(responseCode1 >=300 ) {
connection.disconnect();
throw new ResponseException(responseCode + " "+response.message());
}else {
long contentLength1 =(long)connection.getHeaderFieldInt("Content-Length",-1);
boolean fromCache = Utils.parseResponseSourceHeader(connection,getHeaderField("X-Andro");
return new Response(connection.getInputStream(),fromCache, contentLength1);
}
}
5.into方法,完成加载。
BitmapHunter.run()
BitmapHunter.run()
↓
dispatcher.dispatchComplete(this);//成功的回调
↓
this.handler.sendMessage(this.handler.obtainMessage(4, hunter);
↓
case 4:
{
info2 = (BitmapHunter)msg.obj;
this.dispatcher.performComplete(info2);
} break;
↓
void performComplete(BitmapHunter hunter){
if(MemoryPolicy.shouldWriteToMemoryCache(hunter.getMemoryPolicy())){
this.cache.set(hunter.getKey(), hunter.getResult()); //结果保存到cache 缓存中
}
this.hunterMap.remove(hunter.getKey());//移除hunter.getKey(),请求已完成,避免重复请求
this.batch(hunter);//
if(hunter.getPicasso().loggingEnabled){
Utils.1og("Dispatcher"."batched",Utils.getLogIdsForHunter(hunter),"for completion");
}
}
private void batch(BitmapHunter hunter){
if(!hunter.isCancelled()) {
this.batch.add(hunter); //存放到list集合中
if(!this.handler.hasMessages(7)){
this.handler.sendEmptyMessageDelayed(7, 200L);
}
}
}
// handleMessage()
case 7: this.dispatcher.performBatchComplete();
// performBatchComplete()
void performBatchComplete(){
ArrayList copy=new ArrayList(this.batch);
this.batch.clear(); //清理以前的batch集合
//发消息给主线程处理。
this.mainThreadHandler.sendMessage(this,mainThreadHandler.obtainMessage(8, copy));
this.logBatch(copy);
}
//Picasso.deliverAction()
case 8:
batch = (List)msg.obj;
i =0;
for(n=batch.size(); i<n; ++i){
BitmapHunter var7 = (BitmapHunter)batch.get(i);
var7.picasso.complete(var7);
}
break;
//complete()
void complete(BitmapHunter hunter) {
//...
if(shouldDeliver) {
Uri uri = hunter.getData().uri;
Bitmap result = hunter.getResult();
// 分发action
this.deliverAction(result, from, single);
}
}
// deliverAction
action.complete(result, from); //complete是抽象方法,
//实现类ImageViewAction.java
public void complete(Bitmap result,LoadedFrom from) {
if(result == null){
throw new AssertionError("Attempted to complete action with no result!\n");
}else {
ImageView target=(ImageView)this.target.get();
if(target != null){
Context context=this.picasso.context;
boolean indicatorsEnabled = this.picasso.indicatorsEnabled;
PicassoDrawable.setBitmap(target,context,result, from, this.noFade, indicatorsEnabled);
if(this.callback != null){
this.callback.onSuccess();
}
}
}
}
// PicassoDrawable.java
static void setBitmap(ImageView target, Context context, Bitmap bitmap, Loadedfrom loadedfrom,noFade, indicatorsEnabled) {
Drawable placeholder=target.getDrawable();\
if(placeholder instanceof AnimationDrawable) {
((AnimationDrawable)placeholder).stop();
}
PicassoDrawable drawable = new PicassoDrawable(context, bitmap, placeholder, loadedFrom, nof);
target.setImageDrawable(drawable); //设置图片。
}
重点知识:handler+ 线程池。
------End-----------------