Android框架源码解析之(四)Picasso

Android框架源码解析之(四)Picasso_第1张图片

这次要分析的源码是 Picasso 2.5.2 ,四年前的版本,用eclipse写的,但不影响这次我们对其源码的分析
地址:https://github.com/square/picasso/tree/picasso-parent-2.5.2

Picasso的简单使用

 Picasso.with(this)
        .load("http://ww3.sinaimg.cn/large/610dc034jw1fasakfvqe1j20u00mhgn2.jpg")
        .into(mImageView);

清晰简洁

Picasso的源码分析

首先看一下基本流程
Android框架源码解析之(四)Picasso_第2张图片

Picasso的总体流程:
1)将请求封装为Request对象,然后将Request对象进一步封装为Action(ImageAction)对象。
2)将Action(ImageAction)对象交给Dispather进行分发
3)最终将action交给BitmapHunter这个Runnable作为在线程池中线程的工作的单元(具体的是讲action持有的当前Reqeuest对象)
4)由RequestHandler来处理当前request,调用其load方法将加载完成后的图片交给PicassoDrawable显示图片。
代码流程如下:Picasso->load->创建request->创建action->Dispatcher分发action->RequestHandler的load方法处理具体的请求->PicassoDrawable显示图片。

下面来看细节:

1、Picasso.with()
首先看一下Picasso的构造方法

  Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
      RequestTransformer requestTransformer, List 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.
	
	//用户自定义RequestHandler的数量
    int extraCount = (extraRequestHandlers != null ? extraRequestHandlers.size() : 0);
    List allRequestHandlers =
        new ArrayList(builtInHandlers + extraCount);

	//添加各种RequestHandler
		
	//先添加ResourceRequestHandler
		
		
    // 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();
  }
 
  

with()函数通过双重检查锁模式返回默认Picasso默认实例

   //通过双重检查锁模式  返回Picasso单例对象
  public static Picasso with(Context context) {
    if (singleton == null) {
      synchronized (Picasso.class) {
        if (singleton == null) {
        
        //通过建造者模式,对Picasso进行系统默认设置
        
          singleton = new Builder(context).build();
        }
      }
    }
    return singleton;
  }

通过建造者模式,对Picasso进行系统默认设置

  /** Fluent API for creating {@link Picasso} instances. */
  @SuppressWarnings("UnusedDeclaration") // Public API.
  public static class Builder {
    private final Context context;
    private Downloader downloader;//配置自定义的义图片下载类
    private ExecutorService service;//配置自定义的线程池
    private Cache cache;//配置缓存策略
    private Listener listener;//配置图片下载监听
    private RequestTransformer transformer;//配置图片自定义转换器
    private List requestHandlers;//配置RequestHandler 集合
    private Bitmap.Config defaultBitmapConfig;//配置默认图片设置

    private boolean indicatorsEnabled;
    private boolean loggingEnabled;

    /** Start building a new {@link Picasso} instance. */
    public Builder(Context context) {
      if (context == null) {
        throw new IllegalArgumentException("Context must not be null.");
      }
      this.context = context.getApplicationContext();
    }

    /**
     * Specify the default {@link Bitmap.Config} used when decoding images. This can be overridden
     * on a per-request basis using {@link RequestCreator#config(Bitmap.Config) config(..)}.
     */
    public Builder defaultBitmapConfig(Bitmap.Config bitmapConfig) {
      if (bitmapConfig == null) {
        throw new IllegalArgumentException("Bitmap config must not be null.");
      }
      this.defaultBitmapConfig = bitmapConfig;
      return this;
    }

    /** Specify the {@link Downloader} that will be used for downloading images. */
    public Builder downloader(Downloader downloader) {
      if (downloader == null) {
        throw new IllegalArgumentException("Downloader must not be null.");
      }
      if (this.downloader != null) {
        throw new IllegalStateException("Downloader already set.");
      }
      this.downloader = downloader;
      return this;
    }

    /**
     * Specify the executor service for loading images in the background.
     * 

* Note: Calling {@link Picasso#shutdown() shutdown()} will not shutdown supplied executors. */ public Builder executor(ExecutorService executorService) { if (executorService == null) { throw new IllegalArgumentException("Executor service must not be null."); } if (this.service != null) { throw new IllegalStateException("Executor service already set."); } this.service = executorService; return this; } /** Specify the memory cache used for the most recent images. */ public Builder memoryCache(Cache memoryCache) { if (memoryCache == null) { throw new IllegalArgumentException("Memory cache must not be null."); } if (this.cache != null) { throw new IllegalStateException("Memory cache already set."); } this.cache = memoryCache; return this; } /** Specify a listener for interesting events. */ public Builder listener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("Listener must not be null."); } if (this.listener != null) { throw new IllegalStateException("Listener already set."); } this.listener = listener; return this; } /** * Specify a transformer for all incoming requests. *

* NOTE: This is a beta feature. The API is subject to change in a backwards incompatible * way at any time. */ public Builder requestTransformer(RequestTransformer transformer) { if (transformer == null) { throw new IllegalArgumentException("Transformer must not be null."); } if (this.transformer != null) { throw new IllegalStateException("Transformer already set."); } this.transformer = transformer; return this; } /** Register a {@link RequestHandler}. */ public Builder addRequestHandler(RequestHandler requestHandler) { if (requestHandler == null) { throw new IllegalArgumentException("RequestHandler must not be null."); } if (requestHandlers == null) { requestHandlers = new ArrayList(); } if (requestHandlers.contains(requestHandler)) { throw new IllegalStateException("RequestHandler already registered."); } requestHandlers.add(requestHandler); return this; } /** * @deprecated Use {@link #indicatorsEnabled(boolean)} instead. * Whether debugging is enabled or not. */ @Deprecated public Builder debugging(boolean debugging) { return indicatorsEnabled(debugging); } /** Toggle whether to display debug indicators on images. */ public Builder indicatorsEnabled(boolean enabled) { this.indicatorsEnabled = enabled; return this; } /** * Toggle whether debug logging is enabled. *

* WARNING: Enabling this will result in excessive object allocation. This should be only * be used for debugging purposes. Do NOT pass {@code BuildConfig.DEBUG}. */ public Builder loggingEnabled(boolean enabled) { this.loggingEnabled = enabled; return this; } /** 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); } }

可以看出with()函数主要 使用单例模式(双重检查锁)创建Picasso实例,并使用建造者模式 对Picasso进行初始化配置。

2、Picasso.load()

 //创建RequestCreator
  public RequestCreator load(Uri uri) {
    return new RequestCreator(this, uri, 0);
  }

  /**
   * Start an image request using the specified path. This is a convenience method for calling
   * {@link #load(Uri)}.
   * 

* This path may be a remote URL, file resource (prefixed with {@code file:}), content resource * (prefixed with {@code content:}), or android resource (prefixed with {@code * android.resource:}. *

* Passing {@code null} as a {@code path} will not trigger any request but will set a * placeholder, if one is specified. * * @see #load(Uri) * @see #load(File) * @see #load(int) * @throws IllegalArgumentException if {@code path} is empty or blank string. */ public RequestCreator load(String path) { if (path == null) { return new RequestCreator(this, null, 0); } if (path.trim().length() == 0) { throw new IllegalArgumentException("Path must not be empty."); } return load(Uri.parse(path)); } /** * Start an image request using the specified image file. This is a convenience method for * calling {@link #load(Uri)}. *

* Passing {@code null} as a {@code file} will not trigger any request but will set a * placeholder, if one is specified. *

* Equivalent to calling {@link #load(Uri) load(Uri.fromFile(file))}. * * @see #load(Uri) * @see #load(String) * @see #load(int) */ public RequestCreator load(File file) { if (file == null) { return new RequestCreator(this, null, 0); } return load(Uri.fromFile(file)); } /** * Start an image request using the specified drawable resource ID. * * @see #load(Uri) * @see #load(String) * @see #load(File) */ public RequestCreator load(int resourceId) { if (resourceId == 0) { throw new IllegalArgumentException("Resource ID must not be zero."); } return new RequestCreator(this, null, resourceId); }

可以看出这几种重载方法 目的都是为了创建RequestCreator 对象

//让我们来看看RequestCreator的构造方法

  RequestCreator(Picasso picasso, Uri uri, int resourceId) {
    if (picasso.shutdown) {
      throw new IllegalStateException(
          "Picasso instance already shut down. Cannot submit new requests.");
    }
    this.picasso = picasso;
//接着创建了Request对象
    this.data = new Request.Builder(uri, resourceId, picasso.defaultBitmapConfig);
  }

调用load方法的时候实际上并没有对图片资源进行加载,只是简单返回了一个RequestCreator对象,该对象在初始化的时候初始化了Request的Builder对象

3、RequestCreator.into()
使用过Picasso的都知道,我们调用RequestCreator的into方法来完成工作的,那么就先简单的分析RequestCreator的into系列重载方法之一进行说明

  public void into(ImageView target, Callback callback) {
    long started = System.nanoTime();
	//检查是否在主线程
    checkMain();

    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 request = createRequest(started);
	//创建请求的key
    String requestKey = createKey(request);

    if (shouldReadFromMemoryCache(memoryPolicy)) {
      Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
      if (bitmap != null) {
        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,实际上是一个ImageViewAction

    Action action =
        new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
            errorDrawable, requestKey, tag, callback, noFade);

			
	//提交Action
    picasso.enqueueAndSubmit(action);
  }

继续查看 picasso.enqueueAndSubmit(action)

  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.dispatchSubmit(action);

  void dispatchSubmit(Action action) {
    
    //这里调用了handler发送消息
     

	handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action));
  }


    @Override public void handleMessage(final Message msg) {
      switch (msg.what) {
        case REQUEST_SUBMIT: {
          Action action = (Action) msg.obj;

//重点在这
          dispatcher.performSubmit(action);
          break;
        }

继续跟进dispatcher.performSubmit(action);

  void performSubmit(Action action) {
    performSubmit(action, true);
  }

  void performSubmit(Action action, boolean dismissFailed) {
    if (pausedTags.contains(action.getTag())) {
      pausedActions.put(action.getTarget(), action);
      if (action.getPicasso().loggingEnabled) {
        log(OWNER_DISPATCHER, VERB_PAUSED, action.request.logId(),
            "because tag '" + action.getTag() + "' is paused");
      }
      return;
    }

	//BitmapHunter获取了请求的key,Hunter是一个runnable
    BitmapHunter hunter = hunterMap.get(action.getKey());
    if (hunter != null) {
      hunter.attach(action);
      return;
    }

    if (service.isShutdown()) {
      if (action.getPicasso().loggingEnabled) {
        log(OWNER_DISPATCHER, VERB_IGNORED, action.request.logId(), "because shut down");
      }
      return;
    }
	
	
	//重点在这   forRequest();

    hunter = forRequest(action.getPicasso(), this, cache, stats, action);
	//提交
    hunter.future = service.submit(hunter);
    hunterMap.put(action.getKey(), hunter);
    if (dismissFailed) {
      failedActions.remove(action.getTarget());
    }

    if (action.getPicasso().loggingEnabled) {
      log(OWNER_DISPATCHER, VERB_ENQUEUED, action.request.logId());
    }
  }

继续跟进forRequest();

static BitmapHunter forRequest(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats,
      Action action) {
    //获取当前请求对象
    Request request = action.getRequest();
    //获取picasso内置的RequestHandler对象和自定义的RequestHandler对象
    List requestHandlers = picasso.getRequestHandlers();
    //判断内置对象或者自定义的对象哪一个对象能处理当前请求
    for (int i = 0, count = requestHandlers.size(); i < count; i++) {
      RequestHandler requestHandler = requestHandlers.get(i);
      if (requestHandler.canHandleRequest(request)) {//如果能处理当前请求
        //返回一个bitMapHandler
        //把当前ReqeuestHandler对象交给BitmapHunter
        return new BitmapHunter(picasso, dispatcher, cache, stats, action, requestHandler);
      }
    }
    //说明当前请求无效
    return new BitmapHunter(picasso, dispatcher, cache, stats, action, ERRORING_HANDLER);
  }

上面forRequest方法也很简单:主要执行了一下逻辑
1、获取当前请求Reqeuest对象
2、获取Picasso内置的RequestHandler以及自定义的RequestHandler集合。
3、判断集合中哪一个RequestHandler对象可以对当前Reqeuest进行处理(canHanlderReqest返回true)
4、把集合中能处理当前Request的RequestHandler对象交给BitMapHunter。

Action的简单说明:
Action所有的属性如下:

final Picasso picasso;//持有上文单利引用
  final Request request;//上文提到的request
  final WeakReference target;//target可能是ImageView,或者优先理解为ImageView,为弱引用,确保target被回收的时候不受影响
  final boolean noFade;
  final int memoryPolicy;//缓存策略
  final int networkPolicy;//
  final int errorResId;
  final Drawable errorDrawable;
  final String key;
  final Object tag;
  boolean willReplay;
  boolean cancelled;

Action的主要职责就是:对图片进行加载,配置图片的文件缓存和内存缓存策略以及是否重新加载等逻辑。使得责任分明,调理清晰。

Action是一个抽象的泛型类,提供了complete和error两个抽象方法

  abstract void complete(Bitmap result, Picasso.LoadedFrom from);

  abstract void error();

它的子类又如下几个:
GetAction、FetchAction、ImageViewAction、TargetAction在此处我们提交的是ImageViewAction.
让我们简单的看一下ImageViewAction的complete方法:

  @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;
	//设置图片    
	PicassoDrawable.setBitmap(target, context, result, from, noFade, indicatorsEnabled);

	//设置callback
    if (callback != null) {
      callback.onSuccess();
    }
  }

可以发现最终是由PicassoDrawable来完成图片的显示,所以继续跟进:
PicasDrawable是BitmapDrawable的子类:

final class PicassoDrawable extends BitmapDrawable {
  static void setBitmap(ImageView target, Context context, Bitmap bitmap,
      Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) {
      //获取drawable
    Drawable placeholder = target.getDrawable();
    if (placeholder instanceof AnimationDrawable) {
      ((AnimationDrawable) placeholder).stop();
    }
    //创建
    PicassoDrawable drawable =
        new PicassoDrawable(context, bitmap, placeholder, loadedFrom, noFade, debugging);
        //显示
    target.setImageDrawable(drawable);
  }
//最终将图片显示出来
}

RequestHandler
该类用来处理不同来源的图片,是个抽象类。
在picasso只是用面向对象的方式处理来自网络(NetworkRequestHandler),Resoure资源图片(ResourceRequestHandler),asset文件中的图片(AssetRequestHandler)等等若干个Handler。在初始化Picasso的时候,Picasso默认实现的RequestHandler的上述子类是预加载到一个集合中去的!

Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
      RequestTransformer requestTransformer, List extraRequestHandlers, Stats stats,
      Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled) {


...........................

/用户自定义RequestHandler的数量
    int extraCount = (extraRequestHandlers != null ? extraRequestHandlers.size() : 0);
    List allRequestHandlers =
        new ArrayList(builtInHandlers + extraCount);

	//添加各种RequestHandler
		
	//先添加ResourceRequestHandler
		
		
    // 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);



}

Picasso自己实现的handler在构造器初始化的时候就把自己实现的RequestHander的子类预先初始化好(姑且称之为Picasso内置的ReqeustHandler对象),当然用户也可以实现自己的RequestHandler通过Picasso.Builder.addRequestHandler来添加进去,当然大多数情况不需要自己提供ReqeuestHandler的实现。

那Picasso怎么知道是来自于哪个种类的图片呢?这就是ReqeuestHandler的功能了!RequestHandler时候一个抽象类,从名字上就可以知道它是处理具体请求的,它提供了两个重要的抽象方法来完成对不同种类图片的处理工作:

  /**
   * Whether or not this {@link RequestHandler} can handle a request with the given {@link Request}.
   */
//判断某子类是否有能力处理当前请求 
  public abstract boolean canHandleRequest(Request data);

  /**
   * Loads an image for the given {@link Request}.
   *
   * @param request the data from which the image should be resolved.
   * @param networkPolicy the {@link NetworkPolicy} for this request.
   * 
   */
//在canHandleRequest方法返回true的时候,就用该RequestHandler的实现类的load方法来加载图片!
  public abstract Result load(Request request, int networkPolicy) throws IOException;

简单分析一下
Picasso怎么处理网络Reqeust的:NetworkRequestHandler

//判断当前请求的图片资源是否来自于服务器或者网络
public boolean canHandleRequest(Request data) {
    String scheme = data.uri.getScheme();
    return (SCHEME_HTTP.equals(scheme) || SCHEME_HTTPS.equals(scheme));
  }
//NetWorkReqesutHandler对load的处理  
public Result load(Request request, int networkPolicy) throws IOException {
    //下载图片资源,返回一个Response对象
    Response response = downloader.load(request.uri, request.networkPolicy);
    if (response == null) {
      return null;
    }

    Picasso.LoadedFrom loadedFrom = response.cached ? DISK : NETWORK;
    Bitmap bitmap = response.getBitmap();
    if (bitmap != null) {
      return new Result(bitmap, loadedFrom);
    }

    InputStream is = response.getInputStream();
    if (is == null) {
      return null;
    }
     。。。此处有省略代码。。。
    return new Result(is, loadedFrom);
  }

Picasso怎么处理ResourceReqeust的:ResourceRequestHandler

  @Override
   public boolean canHandleRequest(Request data) {
	  //若资源id不为0,则判断为为Resource,能加载
    if (data.resourceId != 0) {
      return true;
    }

	//判断文件scheme是否为 RESOURCE
    return SCHEME_ANDROID_RESOURCE.equals(data.uri.getScheme());
  }

  @Override
   public Result load(Request request, int networkPolicy) throws IOException {
	  //加载Resource文件(R文件引用)
    Resources res = Utils.getResources(context, request);
    int id = Utils.getResourceId(res, request);
    return new Result(decodeResource(res, id, request), DISK);
  }

Picasso怎么处理FileReqeust的:FileRequestHandler

  @Override public boolean canHandleRequest(Request data) {
    //判断文件scheme是否为FILE
	return SCHEME_FILE.equals(data.uri.getScheme());
  }

  @Override public Result load(Request request, int networkPolicy) throws IOException {
    return new Result(null, getInputStream(request), DISK, getFileExifRotation(request.uri));
  }

其他文件来源均类似

注意此时Picasso并没有立即调用RequestHandler对象的load方法进行处理,而是继续调用 service.submit(hunter);方法来在线程池中对BitmapHunter这个Runnable进行处理,所以我们不难猜测出来在run方法中必然调用了RequestHandler的load方法!

那么就继续追踪BimapHunter的run方法发现其调用了hunt()方法,那么hunt()方法是由做了什么

//BitmapHunter的run方法
public void run() { 
    result = hunt();//获取执行结果
 }
//注意该方法返回了一个bitmap
 Bitmap hunt() throws IOException {
    Bitmap bitmap = null;

    //获取读取内存代码省略
    data.networkPolicy = retryCount == 0 ? NetworkPolicy.OFFLINE.index : networkPolicy;
    //此处真是调用了load方法进行处理
    RequestHandler.Result result = requestH andler.load(data, networkPolicy);
     ....此处省略大量代码....
    return bitmap;
  }

在hunt()方法中正式调用了forReqeuset过滤的ReqesutHandler对象的load方法完成了核心业务功能!

Android框架源码解析之(四)Picasso_第3张图片

上面简单的介绍了一下Picasso的工作流程,,希望能对大家有所帮助~~~

你可能感兴趣的:(安卓高级,Android框架源码解析)