package yuku.afw.rpc; import android.content.Context; import android.os.SystemClock; import android.util.Log; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import yuku.afw.D; public class UrlLoader { public static final String TAG = UrlLoader.class.getSimpleName(); static class Data { List<Listener> listeners; long startTime; } Map<String, Data> running = new LinkedHashMap<String, Data>(); public interface Listener { void onResponse(String url, Response response, BaseData data, boolean firstTime); } /** must call this from main thread */ public synchronized boolean load(Context context, final String url, ImageData imageData, Listener listener) { Data data = running.get(url); if (data == null) { // not running, create new final Data newData = new Data(); newData.startTime = SystemClock.uptimeMillis(); newData.listeners = new ArrayList<Listener>(4); newData.listeners.add(listener); // save running.put(url, newData); if (D.EBUG) Log.d(TAG, "Loading url: " + url + " creates a new request with 1 listener"); new AsyncRequest<ImageData>(new UrlImage(url), imageData) { @Override protected void onResponse(Response response, ImageData imageData) { long responseTime = SystemClock.uptimeMillis(); // call all listeners and remove from map try { boolean firstTime = true; for (int i = 0, len = newData.listeners.size(); i < len; i++) { newData.listeners.get(i).onResponse(url, response, imageData, firstTime); firstTime = false; } } finally { running.remove(url); long endTime = SystemClock.uptimeMillis(); if (D.EBUG) Log.d(UrlLoader.TAG, "Loading url: " + url + " finished. Loaded in " + (responseTime - newData.startTime) + " ms, callback in " + (endTime - responseTime) + " ms"); } }; }.start(); return true; } else { // just add listeners data.listeners.add(listener); if (D.EBUG) Log.d(TAG, "Loading url: " + url + " uses existing request, now it has " + data.listeners.size() + " listeners"); return false; } } private static class UrlImage extends Request { public UrlImage(String url) { super(Method.GET_RAW, url); } } }