package com.squareup.picasso;
import android.os.Handler;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* A queue that manages dispatching the BitmapHunter result
*
* @author Hannes Dorfmann
*/
public class DispatchingQueue {
final Map<BitmapHunter, DispatchJob> hunterMap;
final Queue<DispatchJob> jobQueue;
final Handler handler;
boolean dispatching;
public DispatchingQueue(Handler handler) {
this.handler = handler;
this.jobQueue = new ConcurrentLinkedQueue<DispatchJob>();
this.hunterMap = new ConcurrentHashMap<BitmapHunter, DispatchJob>();
this.dispatching = true;
}
public void interruptDispatching() {
Utils.checkMain();
dispatching = false;
}
public void continueDispatching() {
Utils.checkMain();
dispatching = true;
dispatchNextFromQueue();
}
public boolean isDispatchingEnabled() {
return dispatching;
}
private void scheduleJob(DispatchJob job) {
boolean added = jobQueue.offer(job);
if (added) {
hunterMap.put(job.getBitmapHunter(), job);
}
}
public void dispatchComplete(BitmapHunter hunter) {
if (isDispatchingEnabled()) {
// dispatch directly; avoid object creation overhead
handler.sendMessage(handler.obtainMessage(Dispatcher.HUNTER_COMPLETE, hunter));
} else {
// dispatching is disabled temporally
CompleteDispatchJob job = new CompleteDispatchJob(handler, hunter);
scheduleJob(job);
}
}
public void dispatchFailed(BitmapHunter hunter) {
if (isDispatchingEnabled()) {
// dispatch directly; avoid object creation overhead
handler.sendMessage(handler.obtainMessage(Dispatcher.HUNTER_DECODE_FAILED, hunter));
} else {
// dispatching is disabled temporally
FailedDispatchJob job = new FailedDispatchJob(handler, hunter);
scheduleJob(job);
}
}
public void dispatchNextFromQueue() {
while (!jobQueue.isEmpty()) {
DispatchJob job = jobQueue.poll();
if (job != null) {
hunterMap.remove(job.getBitmapHunter());
job.dispatch();
}
}
}
public void dequeue(BitmapHunter hunter) {
DispatchJob job = hunterMap.get(hunter);
if (job != null) {
// Remove the waiting jo from queue
jobQueue.remove(job);
hunterMap.remove(hunter);
}
}
public void clear() {
jobQueue.clear();
hunterMap.clear();
}
/**
* Base class for dispatch jobs
*/
abstract static class DispatchJob {
protected final Handler handler;
protected final BitmapHunter hunter;
protected DispatchJob(Handler handler, BitmapHunter hunter) {
this.handler = handler;
this.hunter = hunter;
}
public BitmapHunter getBitmapHunter() {
return hunter;
}
/**
* Dispatches the message
*/
public abstract void dispatch();
}
/**
* A job that will dispatch that the BitmapHunter has completetd his job
*/
static class CompleteDispatchJob extends DispatchJob {
protected CompleteDispatchJob(Handler handler, BitmapHunter hunter) {
super(handler, hunter);
}
public void dispatch() {
handler.sendMessage(handler.obtainMessage(Dispatcher.HUNTER_COMPLETE, hunter));
}
}
/**
* A job to dispatch that the BitmapHunter has failed
*/
static class FailedDispatchJob extends DispatchJob {
FailedDispatchJob(Handler handler, BitmapHunter hunter) {
super(handler, hunter);
}
public void dispatch() {
handler.sendMessage(handler.obtainMessage(Dispatcher.HUNTER_DECODE_FAILED, hunter));
}
}
}