package com.vaguehope.onosendai.images;
import java.util.concurrent.ExecutionException;
import android.graphics.Bitmap;
import com.vaguehope.onosendai.images.HybridBitmapCache.LoadListener;
import com.vaguehope.onosendai.images.ImageFetcherTask.ImageFetchResult;
import com.vaguehope.onosendai.util.ExcpetionHelper;
import com.vaguehope.onosendai.util.HttpHelper;
import com.vaguehope.onosendai.util.IoHelper;
import com.vaguehope.onosendai.util.LogWrapper;
import com.vaguehope.onosendai.util.StringHelper;
import com.vaguehope.onosendai.util.exec.ExecutorEventListener;
import com.vaguehope.onosendai.util.exec.TrackingAsyncTask;
public class ImageFetcherTask extends TrackingAsyncTask<Void, Object, ImageFetchResult> implements LoadListener {
private static final LogWrapper LOG = new LogWrapper("IF");
private final HybridBitmapCache cache;
private final ImageLoadRequest req;
public ImageFetcherTask (final ExecutorEventListener eventListener, final HybridBitmapCache cache, final ImageLoadRequest req) {
super(eventListener);
this.cache = cache;
this.req = req;
}
@Override
public String toString () {
return "fetch:" + StringHelper.maxLengthEnd(this.req.getUrl(), 40);
}
@Override
protected void onPreExecute () {
this.req.setLoadingProgressIfRequired("fetch pending"); //ES
}
@Override
protected void onProgressUpdate (final Object... values) {
if (values == null || values.length < 1) return;
switch ((Integer) values[0]) {
case 0:
final String msg = (String) values[1];
this.req.setLoadingProgressIfRequired(msg);
this.cache.getReqMgr().setLoadingProgressIfRequired(this.req, msg);
break;
case 1:
final Integer progress = (Integer) values[1];
final Integer total = (Integer) values[2];
this.req.setFetchingProgressIfRequired(progress, total);
this.cache.getReqMgr().setFetchingProgressIfRequired(this.req, progress, total);
if (total < 1) {
final String prgMsg = "fetched " + IoHelper.readableFileSize(progress); //ES
this.req.setLoadingProgressIfRequired(prgMsg);
this.cache.getReqMgr().setLoadingProgressIfRequired(this.req, prgMsg);
}
break;
}
}
/**
* Called on BG thread.
*/
@Override
public void onContentLengthToLoad (final long contentLength) {
publishProgress(0, "loading " + IoHelper.readableFileSize(contentLength)); //ES
}
/**
* Called on BG thread.
*/
@Override
public void onContentLengthToFetch (final long contentLength) {
if (contentLength > 0) {
publishProgress(0, "fetching " + IoHelper.readableFileSize(contentLength)); //ES
}
else {
publishProgress(0, "fetching ?B"); //ES
}
}
/**
* Called on BG thread.
*/
@Override
public void onContentFetching (final int bytesFetched, final int contentLength) {
publishProgress(1, bytesFetched, contentLength);
}
@Override
protected ImageFetchResult doInBackgroundWithTracking (final Void... unused) {
if (!this.req.shouldFinishLoading()) return null;
try {
final String url = this.req.getUrl();
Bitmap bmp = this.cache.get(url, this.req.getReqWidth(), this);
if (bmp == null) {
final String failure1 = this.cache.getFailure(url);
if (failure1 != null) return new ImageFetchResult(this.req, failure1);
final Object sync = this.cache.getSyncMgr().getSync(url);
try {
synchronized (sync) {
bmp = this.cache.get(url, this.req.getReqWidth(), this);
if (bmp == null) {
final String failure2 = this.cache.getFailure(url);
if (failure2 != null) return new ImageFetchResult(this.req, failure2);
LOG.d("Fetching image: '%s'...", url);
publishProgress(0, "fetching"); //ES
bmp = HttpHelper.get(url, this.cache.fromHttp(url, this.req.getReqWidth(), this));
}
}
}
finally {
this.cache.getSyncMgr().returnSync(url);
}
}
return new ImageFetchResult(this.req, bmp);
}
catch (final Exception e) { // NOSONAR To report errors.
return new ImageFetchResult(this.req, e);
}
catch (final Throwable e) { // NOSONAR To report errors.
return new ImageFetchResult(this.req, new ExecutionException("Failed to fetch or load image.", e));
}
}
@Override
protected void onPostExecute (final ImageFetchResult result) {
if (result == null) return; // Request was no longer required.
if (result.isSuccess()) {
result.getRequest().setImageBitmapIfRequired(result.getBmp());
}
else {
LOG.w("Failed to fetch image '%s': %s", result.getRequest().getUrl(), result.getEmsg());
result.getRequest().setImageUnavailableIfRequired(result.getShortEmsg());
}
}
protected static class ImageFetchResult {
private final boolean success;
private final ImageLoadRequest request;
private final Bitmap bmp;
private final Exception e;
private final String errMsg;
public ImageFetchResult (final ImageLoadRequest request, final Bitmap bmp) {
if (request == null) throw new IllegalArgumentException("Missing arg: request.");
this.success = (bmp != null);
this.request = request;
this.bmp = bmp;
this.e = null;
this.errMsg = null;
}
public ImageFetchResult (final ImageLoadRequest request, final Exception e) {
if (request == null) throw new IllegalArgumentException("Missing arg: request.");
if (e == null) throw new IllegalArgumentException("Missing arg: e.");
this.success = false;
this.request = request;
this.bmp = null;
this.e = e;
this.errMsg = null;
}
public ImageFetchResult (final ImageLoadRequest request, final String errMsg) {
if (request == null) throw new IllegalArgumentException("Missing arg: request.");
if (errMsg == null) throw new IllegalArgumentException("Missing arg: e.");
this.success = false;
this.request = request;
this.bmp = null;
this.e = null;
this.errMsg = errMsg;
}
public boolean isSuccess () {
return this.success;
}
public ImageLoadRequest getRequest () {
return this.request;
}
public Bitmap getBmp () {
return this.bmp;
}
public String getEmsg () {
if (this.e != null) return ExcpetionHelper.causeTrace(this.e, "|");
if (this.errMsg != null) return this.errMsg;
return "Unknown error.";
}
public String getShortEmsg () {
if (this.e != null) return ExcpetionHelper.veryShortMessage(this.e);
if (this.errMsg != null) return this.errMsg;
return "Unknown error.";
}
}
}