/*** The global default {@link Picasso} instance.* <p>* This instance is automatically initialized with defaults that are suitable to most* implementations.* <ul>* <li>LRU memory cache of 15% the available application RAM</li>* <li>Disk cache of 2% storage space up to 50MB but no less than 5MB. (Note: this is only* available on API 14+ <em>or</em> if you are using a standalone library that provides a disk* cache on all API levels like OkHttp)</li>* <li>Three download threads for disk and network access.</li>* </ul>* <p>* If these settings do not meet the requirements of your application you can construct your own* with full control over the configuration by using {@link Picasso.Builder} to create a* {@link Picasso} instance. You can either use this directly or by setting it as the global* instance with {@link #setSingletonInstance}.*/public static Picasso with(Context context) {if (singleton == null) {synchronized (Picasso.class) {if (singleton == null) {singleton = new Builder(context).build();}}}return singleton;}
/*** Start an image request using the specified URI.* <p>* Passing {@code null} as a {@code uri} will not trigger any request but will set a placeholder,* if one is specified.** @see #load(File)* @see #load(String)* @see #load(int)*/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)}.* <p>* 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:}.* <p>* 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)}.* <p>* Passing {@code null} as a {@code file} will not trigger any request but will set a* placeholder, if one is specified.* <p>* 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(Picasso picasso, Uri uri, int resourceId) {if (picasso.shutdown) {throw new IllegalStateException("Picasso instance already shut down. Cannot submit new requests.");}this.picasso = picasso;this.data = new Request.Builder(uri, resourceId, picasso.defaultBitmapConfig);}
3.3.3 into()
RequestCreator中很多方法都是我們經常會用到的。先看into()方法
/*** Asynchronously fulfills the request into the specified {@link Target}. In most cases, you* should use this when you are dealing with a custom {@link android.view.View View} or view* holder which should implement the {@link Target} interface.* <p>* Implementing on a {@link android.view.View View}:* <blockquote><pre>* public class ProfileView extends FrameLayout implements Target {* {@literal @}Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {* setBackgroundDrawable(new BitmapDrawable(bitmap));* }** {@literal @}Override public void onBitmapFailed() {* setBackgroundResource(R.drawable.profile_error);* }** {@literal @}Override public void onPrepareLoad(Drawable placeHolderDrawable) {* frame.setBackgroundDrawable(placeHolderDrawable);* }* }* </pre></blockquote>* Implementing on a view holder object for use inside of an adapter:* <blockquote><pre>* public class ViewHolder implements Target {* public FrameLayout frame;* public TextView name;** {@literal @}Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {* frame.setBackgroundDrawable(new BitmapDrawable(bitmap));* }** {@literal @}Override public void onBitmapFailed() {* frame.setBackgroundResource(R.drawable.profile_error);* }** {@literal @}Override public void onPrepareLoad(Drawable placeHolderDrawable) {* frame.setBackgroundDrawable(placeHolderDrawable);* }* }* </pre></blockquote>* <p>* <em>Note:</em> This method keeps a weak reference to the {@link Target} instance and will be* garbage collected if you do not keep a strong reference to it. To receive callbacks when an* image is loaded use {@link #into(android.widget.ImageView, Callback)}.*/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);}/*** Asynchronously fulfills the request into the specified {@link RemoteViews} object with the* given {@code viewId}. This is used for loading bitmaps into a {@link Notification}.*/public void into(RemoteViews remoteViews, int viewId, int notificationId,Notification notification) {long started = System.nanoTime();if (remoteViews == null) {throw new IllegalArgumentException("RemoteViews must not be null.");}if (notification == null) {throw new IllegalArgumentException("Notification must not be null.");}if (deferred) {throw new IllegalStateException("Fit cannot be used with RemoteViews.");}if (placeholderDrawable != null || placeholderResId != 0 || errorDrawable != null) {throw new IllegalArgumentException("Cannot use placeholder or error drawables with remote views.");}Request request = createRequest(started);String key = createKey(request, new StringBuilder()); // Non-main thread needs own builder.RemoteViewsAction action =new NotificationAction(picasso, request, remoteViews, viewId, notificationId, notification,memoryPolicy, networkPolicy, key, tag, errorResId);performRemoteViewInto(action);}/*** Asynchronously fulfills the request into the specified {@link RemoteViews} object with the* given {@code viewId}. This is used for loading bitmaps into all instances of a widget.*/public void into(RemoteViews remoteViews, int viewId, int[] appWidgetIds) {long started = System.nanoTime();if (remoteViews == null) {throw new IllegalArgumentException("remoteViews must not be null.");}if (appWidgetIds == null) {throw new IllegalArgumentException("appWidgetIds must not be null.");}if (deferred) {throw new IllegalStateException("Fit cannot be used with remote views.");}if (placeholderDrawable != null || placeholderResId != 0 || errorDrawable != null) {throw new IllegalArgumentException("Cannot use placeholder or error drawables with remote views.");}Request request = createRequest(started);String key = createKey(request, new StringBuilder()); // Non-main thread needs own builder.RemoteViewsAction action =new AppWidgetAction(picasso, request, remoteViews, viewId, appWidgetIds, memoryPolicy,networkPolicy, key, tag, errorResId);performRemoteViewInto(action);}/*** Asynchronously fulfills the request into the specified {@link ImageView}.* <p>* <em>Note:</em> This method keeps a weak reference to the {@link ImageView} instance and will* automatically support object recycling.*/public void into(ImageView target) {into(target, null);}/*** Asynchronously fulfills the request into the specified {@link ImageView} and invokes the* target {@link Callback} if it's not {@code null}.* <p>* <em>Note:</em> The {@link Callback} param is a strong reference and will prevent your* {@link android.app.Activity} or {@link android.app.Fragment} from being garbage collected. If* you use this method, it is <b>strongly</b> recommended you invoke an adjacent* {@link Picasso#cancelRequest(android.widget.ImageView)} call to prevent temporary leaking.*/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 = createRequest(started);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 action =new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,errorDrawable, requestKey, tag, callback, noFade);picasso.enqueueAndSubmit(action);}
/*** Explicitly opt-out to having a placeholder set when calling {@code into}.* <p>* By default, Picasso will either set a supplied placeholder or clear the target* {@link ImageView} in order to ensure behavior in situations where views are recycled. This* method will prevent that behavior and retain any already set image.*/public RequestCreator noPlaceholder() {if (placeholderResId != 0) {throw new IllegalStateException("Placeholder resource already set.");}if (placeholderDrawable != null) {throw new IllegalStateException("Placeholder image already set.");}setPlaceholder = false;return this;}
4.2 placeholder()
設置占位圖片
/*** A placeholder drawable to be used while the image is being loaded. If the requested image is* not immediately available in the memory cache then this resource will be set on the target* {@link ImageView}.*/public RequestCreator placeholder(int placeholderResId) {if (!setPlaceholder) {throw new IllegalStateException("Already explicitly declared as no placeholder.");}if (placeholderResId == 0) {throw new IllegalArgumentException("Placeholder image resource invalid.");}if (placeholderDrawable != null) {throw new IllegalStateException("Placeholder image already set.");}this.placeholderResId = placeholderResId;return this;}
4.3 error()
設置加載出錯時的圖片
/** An error drawable to be used if the request image could not be loaded. */public RequestCreator error(int errorResId) {if (errorResId == 0) {throw new IllegalArgumentException("Error image resource invalid.");}if (errorDrawable != null) {throw new IllegalStateException("Error image already set.");}this.errorResId = errorResId;return this;}/** An error drawable to be used if the request image could not be loaded. */public RequestCreator error(Drawable errorDrawable) {if (errorDrawable == null) {throw new IllegalArgumentException("Error image may not be null.");}if (errorResId != 0) {throw new IllegalStateException("Error image already set.");}this.errorDrawable = errorDrawable;return this;}
/*** Assign a tag to this request. Tags are an easy way to logically associate* related requests that can be managed together e.g. paused, resumed,* or canceled.* <p>* You can either use simple {@link String} tags or objects that naturally* define the scope of your requests within your app such as a* {@link android.content.Context}, an {@link android.app.Activity}, or a* {@link android.app.Fragment}.** <strong>WARNING:</strong>: Picasso will keep a reference to the tag for* as long as this tag is paused and/or has active requests. Look out for* potential leaks.** @see Picasso#cancelTag(Object)* @see Picasso#pauseTag(Object)* @see Picasso#resumeTag(Object)*/public RequestCreator tag(Object tag) {if (tag == null) {throw new IllegalArgumentException("Tag invalid.");}if (this.tag != null) {throw new IllegalStateException("Tag already set.");}this.tag = tag;return this;}
/*** Attempt to resize the image to fit exactly into the target {@link ImageView}'s bounds. This* will result in delayed execution of the request until the {@link ImageView} has been laid out.* <p>* <em>Note:</em> This method works only when your target is an {@link ImageView}.*/public RequestCreator fit() {deferred = true;return this;}/** Internal use only. Used by {@link DeferredRequestCreator}. */RequestCreator unfit() {deferred = false;return this;}
4.6 resizeDimen() & resize()
調整圖片大小。
/** Resize the image to the specified dimension size. */public RequestCreator resizeDimen(int targetWidthResId, int targetHeightResId) {Resources resources = picasso.context.getResources();int targetWidth = resources.getDimensionPixelSize(targetWidthResId);int targetHeight = resources.getDimensionPixelSize(targetHeightResId);return resize(targetWidth, targetHeight);}/** Resize the image to the specified size in pixels. */public RequestCreator resize(int targetWidth, int targetHeight) {data.resize(targetWidth, targetHeight);return this;}
/*** Crops an image inside of the bounds specified by {@link #resize(int, int)} rather than* distorting the aspect ratio. This cropping technique scales the image so that it fills the* requested bounds and then crops the extra.*/public RequestCreator centerCrop() {data.centerCrop();return this;}/*** Centers an image inside of the bounds specified by {@link #resize(int, int)}. This scales* the image so that both dimensions are equal to or less than the requested bounds.*/public RequestCreator centerInside() {data.centerInside();return this;}
/*** Only resize an image if the original image size is bigger than the target size* specified by {@link #resize(int, int)}.*/public RequestCreator onlyScaleDown() {data.onlyScaleDown();return this;}
4.9 rotate()
旋轉圖片角度,可指定旋轉中心點
/** Rotate the image by the specified degrees. */public RequestCreator rotate(float degrees) {data.rotate(degrees);return this;}/** Rotate the image by the specified degrees around a pivot point. */public RequestCreator rotate(float degrees, float pivotX, float pivotY) {data.rotate(degrees, pivotX, pivotY);return this;}
/*** Attempt to decode the image using the specified config.* <p>* Note: This value may be ignored by {@link BitmapFactory}. See* {@link BitmapFactory.Options#inPreferredConfig its documentation} for more details.*/public RequestCreator config(Bitmap.Config config) {data.config(config);return this;}
4.11 stableKey()
設置固定Key
/*** Sets the stable key for this request to be used instead of the URI or resource ID when* caching. Two requests with the same value are considered to be for the same resource.*/public RequestCreator stableKey(String stableKey) {data.stableKey(stableKey);return this;}
/*** Set the priority of this request.* <p>* This will affect the order in which the requests execute but does not guarantee it.* By default, all requests have {@link Priority#NORMAL} priority, except for* {@link #fetch()} requests, which have {@link Priority#LOW} priority by default.*/public RequestCreator priority(Priority priority) {data.priority(priority);return this;}
/*** Add a custom transformation to be applied to the image.* <p>* Custom transformations will always be run after the built-in transformations.*/// TODO show example of calling resize after a transform in the javadocpublic RequestCreator transform(Transformation transformation) {data.transform(transformation);return this;}/*** Add a list of custom transformations to be applied to the image.* <p>* Custom transformations will always be run after the built-in transformations.*/public RequestCreator transform(List<? extends Transformation> transformations) {data.transform(transformations);return this;}
/*** Specifies the {@link MemoryPolicy} to use for this request. You may specify additional policy* options using the varargs parameter.*/public RequestCreator memoryPolicy(MemoryPolicy policy, MemoryPolicy... additional) {if (policy == null) {throw new IllegalArgumentException("Memory policy cannot be null.");}this.memoryPolicy |= policy.index;if (additional == null) {throw new IllegalArgumentException("Memory policy cannot be null.");}if (additional.length > 0) {for (MemoryPolicy memoryPolicy : additional) {if (memoryPolicy == null) {throw new IllegalArgumentException("Memory policy cannot be null.");}this.memoryPolicy |= memoryPolicy.index;}}return this;}
/*** Specifies the {@link NetworkPolicy} to use for this request. You may specify additional policy* options using the varargs parameter.*/public RequestCreator networkPolicy(NetworkPolicy policy, NetworkPolicy... additional) {if (policy == null) {throw new IllegalArgumentException("Network policy cannot be null.");}this.networkPolicy |= policy.index;if (additional == null) {throw new IllegalArgumentException("Network policy cannot be null.");}if (additional.length > 0) {for (NetworkPolicy networkPolicy : additional) {if (networkPolicy == null) {throw new IllegalArgumentException("Network policy cannot be null.");}this.networkPolicy |= networkPolicy.index;}}return this;}
4.16 noFade()
去掉默認的圖片加載過程中的漸入效果
/** Disable brief fade in of images loaded from the disk cache or network. */public RequestCreator noFade() {noFade = true;return this;}
/*** Synchronously fulfill this request. Must not be called from the main thread.* <p>* <em>Note</em>: The result of this operation is not cached in memory because the underlying* {@link Cache} implementation is not guaranteed to be thread-safe.*/public Bitmap get() throws IOException {long started = System.nanoTime();checkNotMain();if (deferred) {throw new IllegalStateException("Fit cannot be used with get.");}if (!data.hasImage()) {return null;}Request finalData = createRequest(started);String key = createKey(finalData, new StringBuilder());Action action = new GetAction(picasso, finalData, memoryPolicy, networkPolicy, tag, key);return forRequest(picasso, picasso.dispatcher, picasso.cache, picasso.stats, action).hunt();}
/*** Asynchronously fulfills the request without a {@link ImageView} or {@link Target},* and invokes the target {@link Callback} with the result. This is useful when you want to warm* up the cache with an image.* <p>* <em>Note:</em> The {@link Callback} param is a strong reference and will prevent your* {@link android.app.Activity} or {@link android.app.Fragment} from being garbage collected* until the request is completed.*/public void fetch(Callback callback) {long started = System.nanoTime();if (deferred) {throw new IllegalStateException("Fit cannot be used with fetch.");}if (data.hasImage()) {// Fetch requests have lower priority by default.if (!data.hasPriority()) {data.priority(Priority.LOW);}Request request = createRequest(started);String key = createKey(request, new StringBuilder());Bitmap bitmap = picasso.quickMemoryCacheCheck(key);if (bitmap != null) {if (picasso.loggingEnabled) {log(OWNER_MAIN, VERB_COMPLETED, request.plainId(), "from " + MEMORY);}if (callback != null) {callback.onSuccess();}} else {Action action =new FetchAction(picasso, request, memoryPolicy, networkPolicy, tag, key, callback);picasso.submit(action);}}}
/*** Set the global instance returned from {@link #with}.* <p>* This method must be called before any calls to {@link #with} and may only be called once.*/public static void setSingletonInstance(Picasso picasso) {synchronized (Picasso.class) {if (singleton != null) {throw new IllegalStateException("Singleton instance already exists.");}singleton = picasso;}}