/*
* Copyright 2015. Appsi Mobile
*
* 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.appsimobile.appsii.plugins;
import android.app.ActivityManager;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.appsimobile.appsii.compat.MapCompat;
import java.lang.ref.WeakReference;
import java.util.Map;
import javax.inject.Inject;
public class IconCache {
private static IconCache sInstance;
// the lru cache maintains a list of all cached icons
private final LruCache<CacheKey, Bitmap> mCache;
// the weakCache will hold on to any icon really in use.
// by using this we prevent loading icons twice
private final Map<CacheKey, WeakReference<Bitmap>> mWeakCache = MapCompat.createMap();
private final int mCacheSize;
@Inject
public IconCache(ActivityManager activityManager) {
final int memClass = activityManager.getMemoryClass();
int sizeInBytes = memClass * 1024 * 1024;
int desiredSize = sizeInBytes / 20;
// for 50 mb devices this will be 2.5 mb
// for 12 mb devices this is 0.6 mb
mCacheSize = desiredSize;
mCache = new LruCache<CacheKey, Bitmap>(desiredSize) {
@Override
protected int sizeOf(CacheKey key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
public void onClose() {
mCache.trimToSize((int) (mCacheSize / 1.5));
}
public void cacheIcon(String externalId, String method, Bitmap result, boolean large) {
cacheIcon(new CacheKey(externalId, method, large), result);
}
private void cacheIcon(CacheKey cn, Bitmap result) {
mCache.put(cn, result);
mWeakCache.put(cn, new WeakReference<>(result));
}
public Bitmap getCachedIcon(String iconResolveUriPrefix, String externalId, boolean large) {
CacheKey c = new CacheKey(externalId, iconResolveUriPrefix, large);
Bitmap result = mCache.get(c);
if (result == null) {
WeakReference<Bitmap> b = mWeakCache.get(c);
if (b != null) {
result = b.get();
}
if (result != null) {
// add it to the cache again so that the cache knows it is in use
// and lru hit is know. also the memory limits are more realistic
mCache.put(c, result);
}
}
return result;
}
void onTrimMemory(int level) {
mCache.evictAll();
}
void onLowMemory() {
mCache.evictAll();
}
public void clearAllIcons() {
mCache.evictAll();
mWeakCache.clear();
}
// public static Bitmap loadApplicationIcon(String uriPrefix, String id, int w, int h) {
//
// return AppIconHelper.loadIcon(cn, w, h);
// }
static class CacheKey {
final String mExternalId;
final String mIconResolveUriPrefix;
final boolean mLargeImage;
int mHashCode;
boolean mHashcodeValid = false;
public CacheKey(String externalId, String method, boolean largeImage) {
mExternalId = externalId;
mIconResolveUriPrefix = method;
mLargeImage = largeImage;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
CacheKey other = (CacheKey) obj;
if (mLargeImage != other.mLargeImage) {
return false;
}
if (mExternalId == null) {
if (other.mExternalId != null) return false;
} else if (!mExternalId.equals(other.mExternalId)) {
return false;
}
if (mIconResolveUriPrefix == null) {
if (other.mIconResolveUriPrefix != null) return false;
} else if (!mIconResolveUriPrefix.equals(other.mIconResolveUriPrefix)) {
return false;
}
return true;
}
@Override
public synchronized int hashCode() {
if (mHashcodeValid) {
return mHashCode;
}
mHashcodeValid = true;
final int prime = 31;
int result = 1;
result = prime * result
+ ((mExternalId == null) ? 0 : mExternalId.hashCode());
result = prime
* result
+ ((mIconResolveUriPrefix == null) ? 0
: mIconResolveUriPrefix.hashCode());
result = prime * result + (mLargeImage ? 1231 : 1237);
mHashCode = result;
return result;
}
}
}