mobile/android/thirdparty/com/squareup/picasso/RequestCreator.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  * Copyright (C) 2013 Square, Inc.
     3  *
     4  * Licensed under the Apache License, Version 2.0 (the "License");
     5  * you may not use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *      http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.
    15  */
    16 package com.squareup.picasso;
    18 import android.content.res.Resources;
    19 import android.graphics.Bitmap;
    20 import android.graphics.drawable.Drawable;
    21 import android.net.Uri;
    22 import android.widget.ImageView;
    23 import java.io.IOException;
    25 import static com.squareup.picasso.BitmapHunter.forRequest;
    26 import static com.squareup.picasso.Picasso.LoadedFrom.MEMORY;
    27 import static com.squareup.picasso.Utils.checkNotMain;
    28 import static com.squareup.picasso.Utils.createKey;
    30 /** Fluent API for building an image download request. */
    31 @SuppressWarnings("UnusedDeclaration") // Public API.
    32 public class RequestCreator {
    33   private final Picasso picasso;
    34   private final Request.Builder data;
    36   private boolean skipMemoryCache;
    37   private boolean noFade;
    38   private boolean deferred;
    39   private int placeholderResId;
    40   private Drawable placeholderDrawable;
    41   private int errorResId;
    42   private Drawable errorDrawable;
    44   RequestCreator(Picasso picasso, Uri uri, int resourceId) {
    45     if (picasso.shutdown) {
    46       throw new IllegalStateException(
    47           "Picasso instance already shut down. Cannot submit new requests.");
    48     }
    49     this.picasso = picasso;
    50     this.data = new Request.Builder(uri, resourceId);
    51   }
    53   /**
    54    * A placeholder drawable to be used while the image is being loaded. If the requested image is
    55    * not immediately available in the memory cache then this resource will be set on the target
    56    * {@link ImageView}.
    57    */
    58   public RequestCreator placeholder(int placeholderResId) {
    59     if (placeholderResId == 0) {
    60       throw new IllegalArgumentException("Placeholder image resource invalid.");
    61     }
    62     if (placeholderDrawable != null) {
    63       throw new IllegalStateException("Placeholder image already set.");
    64     }
    65     this.placeholderResId = placeholderResId;
    66     return this;
    67   }
    69   /**
    70    * A placeholder drawable to be used while the image is being loaded. If the requested image is
    71    * not immediately available in the memory cache then this resource will be set on the target
    72    * {@link ImageView}.
    73    * <p>
    74    * If you are not using a placeholder image but want to clear an existing image (such as when
    75    * used in an {@link android.widget.Adapter adapter}), pass in {@code null}.
    76    */
    77   public RequestCreator placeholder(Drawable placeholderDrawable) {
    78     if (placeholderResId != 0) {
    79       throw new IllegalStateException("Placeholder image already set.");
    80     }
    81     this.placeholderDrawable = placeholderDrawable;
    82     return this;
    83   }
    85   /** An error drawable to be used if the request image could not be loaded. */
    86   public RequestCreator error(int errorResId) {
    87     if (errorResId == 0) {
    88       throw new IllegalArgumentException("Error image resource invalid.");
    89     }
    90     if (errorDrawable != null) {
    91       throw new IllegalStateException("Error image already set.");
    92     }
    93     this.errorResId = errorResId;
    94     return this;
    95   }
    97   /** An error drawable to be used if the request image could not be loaded. */
    98   public RequestCreator error(Drawable errorDrawable) {
    99     if (errorDrawable == null) {
   100       throw new IllegalArgumentException("Error image may not be null.");
   101     }
   102     if (errorResId != 0) {
   103       throw new IllegalStateException("Error image already set.");
   104     }
   105     this.errorDrawable = errorDrawable;
   106     return this;
   107   }
   109   /**
   110    * Attempt to resize the image to fit exactly into the target {@link ImageView}'s bounds. This
   111    * will result in delayed execution of the request until the {@link ImageView} has been measured.
   112    * <p/>
   113    * <em>Note:</em> This method works only when your target is an {@link ImageView}.
   114    */
   115   public RequestCreator fit() {
   116     deferred = true;
   117     return this;
   118   }
   120   /** Internal use only. Used by {@link DeferredRequestCreator}. */
   121   RequestCreator unfit() {
   122     deferred = false;
   123     return this;
   124   }
   126   /** Resize the image to the specified dimension size. */
   127   public RequestCreator resizeDimen(int targetWidthResId, int targetHeightResId) {
   128     Resources resources = picasso.context.getResources();
   129     int targetWidth = resources.getDimensionPixelSize(targetWidthResId);
   130     int targetHeight = resources.getDimensionPixelSize(targetHeightResId);
   131     return resize(targetWidth, targetHeight);
   132   }
   134   /** Resize the image to the specified size in pixels. */
   135   public RequestCreator resize(int targetWidth, int targetHeight) {
   136     data.resize(targetWidth, targetHeight);
   137     return this;
   138   }
   140   /**
   141    * Crops an image inside of the bounds specified by {@link #resize(int, int)} rather than
   142    * distorting the aspect ratio. This cropping technique scales the image so that it fills the
   143    * requested bounds and then crops the extra.
   144    */
   145   public RequestCreator centerCrop() {
   146     data.centerCrop();
   147     return this;
   148   }
   150   /**
   151    * Centers an image inside of the bounds specified by {@link #resize(int, int)}. This scales
   152    * the image so that both dimensions are equal to or less than the requested bounds.
   153    */
   154   public RequestCreator centerInside() {
   155     data.centerInside();
   156     return this;
   157   }
   159   /** Rotate the image by the specified degrees. */
   160   public RequestCreator rotate(float degrees) {
   161     data.rotate(degrees);
   162     return this;
   163   }
   165   /** Rotate the image by the specified degrees around a pivot point. */
   166   public RequestCreator rotate(float degrees, float pivotX, float pivotY) {
   167     data.rotate(degrees, pivotX, pivotY);
   168     return this;
   169   }
   171   /**
   172    * Add a custom transformation to be applied to the image.
   173    * <p/>
   174    * Custom transformations will always be run after the built-in transformations.
   175    */
   176   // TODO show example of calling resize after a transform in the javadoc
   177   public RequestCreator transform(Transformation transformation) {
   178     data.transform(transformation);
   179     return this;
   180   }
   182   /**
   183    * Indicate that this action should not use the memory cache for attempting to load or save the
   184    * image. This can be useful when you know an image will only ever be used once (e.g., loading
   185    * an image from the filesystem and uploading to a remote server).
   186    */
   187   public RequestCreator skipMemoryCache() {
   188     skipMemoryCache = true;
   189     return this;
   190   }
   192   /** Disable brief fade in of images loaded from the disk cache or network. */
   193   public RequestCreator noFade() {
   194     noFade = true;
   195     return this;
   196   }
   198   /** Synchronously fulfill this request. Must not be called from the main thread. */
   199   public Bitmap get() throws IOException {
   200     checkNotMain();
   201     if (deferred) {
   202       throw new IllegalStateException("Fit cannot be used with get.");
   203     }
   204     if (!data.hasImage()) {
   205       return null;
   206     }
   208     Request finalData = picasso.transformRequest(data.build());
   209     String key = createKey(finalData);
   211     Action action = new GetAction(picasso, finalData, skipMemoryCache, key);
   212     return forRequest(picasso.context, picasso, picasso.dispatcher, picasso.cache, picasso.stats,
   213         action, picasso.dispatcher.downloader).hunt();
   214   }
   216   /**
   217    * Asynchronously fulfills the request without a {@link ImageView} or {@link Target}. This is
   218    * useful when you want to warm up the cache with an image.
   219    */
   220   public void fetch() {
   221     if (deferred) {
   222       throw new IllegalStateException("Fit cannot be used with fetch.");
   223     }
   224     if (data.hasImage()) {
   225       Request finalData = picasso.transformRequest(data.build());
   226       String key = createKey(finalData);
   228       Action action = new FetchAction(picasso, finalData, skipMemoryCache, key);
   229       picasso.enqueueAndSubmit(action);
   230     }
   231   }
   233   /**
   234    * Asynchronously fulfills the request into the specified {@link Target}. In most cases, you
   235    * should use this when you are dealing with a custom {@link android.view.View View} or view
   236    * holder which should implement the {@link Target} interface.
   237    * <p>
   238    * Implementing on a {@link android.view.View View}:
   239    * <blockquote><pre>
   240    * public class ProfileView extends FrameLayout implements Target {
   241    *   {@literal @}Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {
   242    *     setBackgroundDrawable(new BitmapDrawable(bitmap));
   243    *   }
   244    *
   245    *   {@literal @}Override public void onBitmapFailed() {
   246    *     setBackgroundResource(R.drawable.profile_error);
   247    *   }
   248    * }
   249    * </pre></blockquote>
   250    * Implementing on a view holder object for use inside of an adapter:
   251    * <blockquote><pre>
   252    * public class ViewHolder implements Target {
   253    *   public FrameLayout frame;
   254    *   public TextView name;
   255    *
   256    *   {@literal @}Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {
   257    *     frame.setBackgroundDrawable(new BitmapDrawable(bitmap));
   258    *   }
   259    *
   260    *   {@literal @}Override public void onBitmapFailed() {
   261    *     frame.setBackgroundResource(R.drawable.profile_error);
   262    *   }
   263    * }
   264    * </pre></blockquote>
   265    * <p>
   266    * <em>Note:</em> This method keeps a weak reference to the {@link Target} instance and will be
   267    * garbage collected if you do not keep a strong reference to it. To receive callbacks when an
   268    * image is loaded use {@link #into(android.widget.ImageView, Callback)}.
   269    */
   270   public void into(Target target) {
   271     if (target == null) {
   272       throw new IllegalArgumentException("Target must not be null.");
   273     }
   274     if (deferred) {
   275       throw new IllegalStateException("Fit cannot be used with a Target.");
   276     }
   278     Drawable drawable =
   279         placeholderResId != 0 ? picasso.context.getResources().getDrawable(placeholderResId)
   280             : placeholderDrawable;
   282     if (!data.hasImage()) {
   283       picasso.cancelRequest(target);
   284       target.onPrepareLoad(drawable);
   285       return;
   286     }
   288     Request finalData = picasso.transformRequest(data.build());
   289     String requestKey = createKey(finalData);
   291     if (!skipMemoryCache) {
   292       Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
   293       if (bitmap != null) {
   294         picasso.cancelRequest(target);
   295         target.onBitmapLoaded(bitmap, MEMORY);
   296         return;
   297       }
   298     }
   300     target.onPrepareLoad(drawable);
   302     Action action = new TargetAction(picasso, target, finalData, skipMemoryCache, requestKey);
   303     picasso.enqueueAndSubmit(action);
   304   }
   306   /**
   307    * Asynchronously fulfills the request into the specified {@link ImageView}.
   308    * <p/>
   309    * <em>Note:</em> This method keeps a weak reference to the {@link ImageView} instance and will
   310    * automatically support object recycling.
   311    */
   312   public void into(ImageView target) {
   313     into(target, null);
   314   }
   316   /**
   317    * Asynchronously fulfills the request into the specified {@link ImageView} and invokes the
   318    * target {@link Callback} if it's not {@code null}.
   319    * <p/>
   320    * <em>Note:</em> The {@link Callback} param is a strong reference and will prevent your
   321    * {@link android.app.Activity} or {@link android.app.Fragment} from being garbage collected. If
   322    * you use this method, it is <b>strongly</b> recommended you invoke an adjacent
   323    * {@link Picasso#cancelRequest(android.widget.ImageView)} call to prevent temporary leaking.
   324    */
   325   public void into(ImageView target, Callback callback) {
   326     if (target == null) {
   327       throw new IllegalArgumentException("Target must not be null.");
   328     }
   330     if (!data.hasImage()) {
   331       picasso.cancelRequest(target);
   332       PicassoDrawable.setPlaceholder(target, placeholderResId, placeholderDrawable);
   333       return;
   334     }
   336     if (deferred) {
   337       if (data.hasSize()) {
   338         throw new IllegalStateException("Fit cannot be used with resize.");
   339       }
   340       int measuredWidth = target.getMeasuredWidth();
   341       int measuredHeight = target.getMeasuredHeight();
   342       if (measuredWidth == 0 || measuredHeight == 0) {
   343         PicassoDrawable.setPlaceholder(target, placeholderResId, placeholderDrawable);
   344         picasso.defer(target, new DeferredRequestCreator(this, target, callback));
   345         return;
   346       }
   347       data.resize(measuredWidth, measuredHeight);
   348     }
   350     Request finalData = picasso.transformRequest(data.build());
   351     String requestKey = createKey(finalData);
   353     if (!skipMemoryCache) {
   354       Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
   355       if (bitmap != null) {
   356         picasso.cancelRequest(target);
   357         PicassoDrawable.setBitmap(target, picasso.context, bitmap, MEMORY, noFade,
   358             picasso.debugging);
   359         if (callback != null) {
   360           callback.onSuccess();
   361         }
   362         return;
   363       }
   364     }
   366     PicassoDrawable.setPlaceholder(target, placeholderResId, placeholderDrawable);
   368     Action action =
   369         new ImageViewAction(picasso, target, finalData, skipMemoryCache, noFade, errorResId,
   370             errorDrawable, requestKey, callback);
   372     picasso.enqueueAndSubmit(action);
   373   }
   374 }

mercurial