blob: ea45b4022e5ae3a8f3103893eeb48f4af35eecdc [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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.android.quicksearchbox;
import com.android.quicksearchbox.util.CachedLater;
import com.android.quicksearchbox.util.Consumer;
import com.android.quicksearchbox.util.Now;
import com.android.quicksearchbox.util.NowOrLater;
import com.android.quicksearchbox.util.NowOrLaterWrapper;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.WeakHashMap;
/**
* Icon loader that caches the results of another icon loader.
*
*/
public class CachingIconLoader implements IconLoader {
private static final boolean DBG = false;
private static final String TAG = "QSB.CachingIconLoader";
private final IconLoader mWrapped;
private final WeakHashMap<String, Entry> mIconCache;
/**
* Creates a new caching icon loader.
*
* @param wrapped IconLoader whose results will be cached.
*/
public CachingIconLoader(IconLoader wrapped) {
mWrapped = wrapped;
mIconCache = new WeakHashMap<String, Entry>();
}
public NowOrLater<Drawable> getIcon(String drawableId) {
if (DBG) Log.d(TAG, "getIcon(" + drawableId + ")");
if (TextUtils.isEmpty(drawableId) || "0".equals(drawableId)) {
return new Now<Drawable>(null);
}
Entry newEntry = null;
NowOrLater<Drawable.ConstantState> drawableState;
synchronized (this) {
drawableState = queryCache(drawableId);
if (drawableState == null) {
newEntry = new Entry();
storeInIconCache(drawableId, newEntry);
}
}
if (drawableState != null) {
return new NowOrLaterWrapper<Drawable.ConstantState, Drawable>(drawableState){
@Override
public Drawable get(Drawable.ConstantState value) {
return value == null ? null : value.newDrawable();
}};
}
NowOrLater<Drawable> drawable = mWrapped.getIcon(drawableId);
newEntry.set(drawable);
storeInIconCache(drawableId, newEntry);
return drawable;
}
public Uri getIconUri(String drawableId) {
return mWrapped.getIconUri(drawableId);
}
private synchronized NowOrLater<Drawable.ConstantState> queryCache(String drawableId) {
NowOrLater<Drawable.ConstantState> cached = mIconCache.get(drawableId);
if (DBG) {
if (cached != null) Log.d(TAG, "Found icon in cache: " + drawableId);
}
return cached;
}
private synchronized void storeInIconCache(String resourceUri, Entry drawable) {
if (drawable != null) {
mIconCache.put(resourceUri, drawable);
}
}
private static class Entry extends CachedLater<Drawable.ConstantState>
implements Consumer<Drawable>{
private NowOrLater<Drawable> mDrawable;
private boolean mGotDrawable;
private boolean mCreateRequested;
public Entry() {
}
public synchronized void set(NowOrLater<Drawable> drawable) {
if (mGotDrawable) throw new IllegalStateException("set() may only be called once.");
mGotDrawable = true;
mDrawable = drawable;
if (mCreateRequested) {
getLater();
}
}
@Override
protected synchronized void create() {
if (!mCreateRequested) {
mCreateRequested = true;
if (mGotDrawable) {
getLater();
}
}
}
private void getLater() {
NowOrLater<Drawable> drawable = mDrawable;
mDrawable = null;
drawable.getLater(this);
}
public boolean consume(Drawable value) {
store(value == null ? null : value.getConstantState());
return true;
}
}
}