/* * Created by LuaView. * Copyright (c) 2017, Alibaba Group. All rights reserved. * * This source code is licensed under the MIT. * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. */ package com.taobao.luaview.cache; import android.app.Application; import android.support.v4.util.LruCache; import java.util.HashMap; import java.util.Map; /** * App级别的引用cache,不会在退出的时候清空 * * @author song * @date 16/1/27 */ public class AppCache { public static final int DEFAULT_LRU_CACHE_PROTOTYPE_SIZE = (int) (1.5 * 1024 * 1024);//1.5M public static final int DEFAULT_LRU_CACHE_SIZE = 5;//5个 public static final String CACHE_METHODS = "cache_methods";//方法名称缓存 public static final String CACHE_PUBLIC_KEY = "cache_public_key";//公钥 public static final String CACHE_METATABLES = "cache_metatables";//metatable缓存 public static final String CACHE_SCRIPTS = "cache_scripts";//脚本文件缓存,占用空间2% public static final String CACHE_PROTOTYPE = "cache_prototype";//lua中间码缓存,占用空间3% //全局静态cache private static Map<String, AppCache> mCachePool; //simple cache private Map<Object, Object> mCache; //lru cache private LuaLruCache mLruCache; /** * on received memory warning * * @param level */ public static void onTrimMemory(int level) { switch (level) { case Application.TRIM_MEMORY_COMPLETE:// = 80; clear all clear(); break; case Application.TRIM_MEMORY_MODERATE:// = 60; clear(CACHE_PROTOTYPE, CACHE_SCRIPTS); break; case Application.TRIM_MEMORY_BACKGROUND:// = 40; clear(CACHE_SCRIPTS); break; case Application.TRIM_MEMORY_UI_HIDDEN:// = 20; clear(CACHE_SCRIPTS); break; case Application.TRIM_MEMORY_RUNNING_CRITICAL:// = 15; break; case Application.TRIM_MEMORY_RUNNING_LOW:// = 10; break; case Application.TRIM_MEMORY_RUNNING_MODERATE:// = 5; break; } } private AppCache() { this(DEFAULT_LRU_CACHE_SIZE); } private AppCache(int size) { mCache = new HashMap<Object, Object>(); if (size > 0) { mLruCache = new LuaLruCache(size); } } /** * get a named cache * * @return */ public static AppCache getPrototpyeCache() { return getCache(CACHE_PROTOTYPE, DEFAULT_LRU_CACHE_PROTOTYPE_SIZE); } public static AppCache getCache(String cacheName) { return getCache(cacheName, DEFAULT_LRU_CACHE_SIZE); } public static AppCache getCache(String cacheName, int size) { if (mCachePool == null) { mCachePool = new HashMap<String, AppCache>(); } if (!mCachePool.containsKey(cacheName)) { final AppCache appCache = new AppCache(size); mCachePool.put(cacheName, appCache); return appCache; } return mCachePool.get(cacheName); } /** * should call when LuaView is destroy */ public static void clear() { if (mCachePool != null) { mCachePool.clear(); } } /** * clear certain cache * * @param keys */ public static void clear(String... keys) { if (mCachePool != null && keys != null) { AppCache appCache = null; for (String key : keys) { if (mCachePool.containsKey(key)) { appCache = mCachePool.remove(key); if (appCache != null) { if (appCache.mCache != null) { appCache.mCache.clear(); } if (appCache.mLruCache != null) { appCache.mLruCache.evictAll(); } } } } } } /** * get from cache * * @param key * @param <T> * @return */ public <T> T get(final Object key) { if (mCache != null && mCache.get(key) != null) { return (T) mCache.get(key); } return null; } /** * get from cache * * @param key * @param <T> * @return */ public <T> T getLru(final Object key) { if (mLruCache != null && mLruCache.get(key) != null) { return (T) mLruCache.getWrap(key); } return null; } /** * update cache * * @param key * @param value * @param <T> * @return */ public <T> T put(final Object key, T value) { if (mCache != null) { mCache.put(key, value); } return value; } /** * update cache * * @param key * @param value * @param <T> * @return */ public <T> T putLru(final Object key, T value, Integer size) { if (mLruCache != null) { mLruCache.putWrap(key, value, size); } return value; } public <T> T putLru(final Object key, T value) { if (mLruCache != null) { mLruCache.putWrap(key, value, null); } return value; } //----------------------------------------extend lru object------------------------------------- static class LuaLruCache extends LruCache<Object, Object> { public LuaLruCache(int maxSize) { super(maxSize); } public void putWrap(Object key, Object value, Integer size) { if (key != null && value != null) { if (size != null) { super.put(key, new WrapLruObject(value, size)); } else { super.put(key, value); } } } public Object getWrap(Object key) { if (key != null) { Object result = super.get(key); if (result instanceof WrapLruObject) { return ((WrapLruObject) result).obj; } else { return result; } } else { return null; } } @Override protected int sizeOf(Object key, Object value) { if (value instanceof WrapLruObject) { return ((WrapLruObject) value).size; } return super.sizeOf(key, value); } } static class WrapLruObject extends Object { Object obj; int size; WrapLruObject(Object obj, int size) { this.obj = obj; this.size = size; } } }