/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.picasso;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.widget.ImageView;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.Future;
import static com.squareup.picasso.Utils.createKey;
class Request implements Runnable {
static final int DEFAULT_RETRY_COUNT = 2;
enum LoadedFrom {
MEMORY(Color.GREEN),
DISK(Color.YELLOW),
NETWORK(Color.RED);
final int debugColor;
private LoadedFrom(int debugColor) {
this.debugColor = debugColor;
}
}
static class RequestWeakReference<T> extends WeakReference<T> {
final Request request;
public RequestWeakReference(Request request, T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.request = request;
}
}
final Picasso picasso;
final Uri uri;
final int resourceId;
final WeakReference<ImageView> target;
final PicassoBitmapOptions options;
final List<Transformation> transformations;
final boolean skipCache;
final boolean noFade;
final int errorResId;
final Drawable errorDrawable;
final String key;
Future<?> future;
Bitmap result;
LoadedFrom loadedFrom;
int retryCount;
boolean retryCancelled;
Request(Picasso picasso, Uri uri, int resourceId, ImageView imageView,
PicassoBitmapOptions options, List<Transformation> transformations, boolean skipCache,
boolean noFade, int errorResId, Drawable errorDrawable) {
this.picasso = picasso;
this.uri = uri;
this.resourceId = resourceId;
this.target = new RequestWeakReference<ImageView>(this, imageView, picasso.referenceQueue);
this.options = options;
this.transformations = transformations;
this.skipCache = skipCache;
this.noFade = noFade;
this.errorResId = errorResId;
this.errorDrawable = errorDrawable;
this.retryCount = DEFAULT_RETRY_COUNT;
this.key = createKey(this);
}
Object getTarget() {
return target.get();
}
void complete() {
if (result == null) {
throw new AssertionError(
String.format("Attempted to complete request with no result!\n%s", this));
}
ImageView target = this.target.get();
if (target != null) {
Context context = picasso.context;
boolean debugging = picasso.debugging;
PicassoDrawable.setBitmap(target, context, result, loadedFrom, noFade, debugging);
}
}
void error() {
ImageView target = this.target.get();
if (target == null) {
return;
}
if (errorResId != 0) {
target.setImageResource(errorResId);
} else if (errorDrawable != null) {
target.setImageDrawable(errorDrawable);
}
}
@Override public void run() {
try {
// Change the thread name to contain the target URL for debugging purposes.
Thread.currentThread().setName(Utils.THREAD_PREFIX + getName());
picasso.run(this);
} catch (final Throwable e) {
// If an unexpected exception happens, we should crash the app instead of letting the
// executor swallow it.
picasso.handler.post(new Runnable() {
@Override public void run() {
throw new RuntimeException("An unexpected exception occurred", e);
}
});
} finally {
Thread.currentThread().setName(Utils.THREAD_IDLE_NAME);
}
}
private String getName() {
Uri uri = this.uri;
return uri != null ? uri.getPath() : Integer.toString(resourceId);
}
@Override public String toString() {
return "Request["
+ "hashCode="
+ hashCode()
+ ", picasso="
+ picasso
+ ", uri="
+ uri
+ ", resourceId="
+ resourceId
+ ", target="
+ target
+ ", options="
+ options
+ ", transformations="
+ transformationKeys()
+ ", future="
+ future
+ ", result="
+ result
+ ", retryCount="
+ retryCount
+ ", loadedFrom="
+ loadedFrom
+ ']';
}
String transformationKeys() {
if (transformations == null) {
return "[]";
}
StringBuilder sb = new StringBuilder(transformations.size() * 16);
sb.append('[');
boolean first = true;
for (Transformation transformation : transformations) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(transformation.key());
}
sb.append(']');
return sb.toString();
}
}