我正在使用LRUCache
缓存存储在文件系统上的位图.我根据这里的示例构建了缓存:http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
问题是我在使用应用程序时经常看到OutOfMemory崩溃.我相信当LRUCache驱逐图像为另一个图像腾出空间时,内存不会被释放.
当图像被驱逐时,我添加了对Bitmap.recycle()的调用:
// use 1/8 of the available memory for this memory cache
final int cacheSize = 1024 * 1024 * memClass / 8;
mImageCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount();
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
oldBitmap.recycle();
oldBitmap = null;
}
};
Run Code Online (Sandbox Code Playgroud)
这可以解决崩溃问题,但是它也会导致图像有时不会出现在应用程序中(只是图像所在的黑色空间).任何时候我都会在Logcat中看到这条消息:Cannot generate texture from bitmap
.
一个快速谷歌搜索显示这是发生,因为显示的图像已被回收.
那么这里发生了什么?为什么再循环图像仍然在LRUCache中,如果我只是在它们被删除后回收它们?实现缓存的替代方法是什么?Android文档明确指出LRUCache是可行的方法,但他们没有提到回收位图的必要性或如何做到这一点.
解决: 如果它有用给其他人,由接受的答案建议解决这个问题是不是做什么,我在做上面的代码示例(不回收的位图 …
我需要帮助了解androids LruCache.我想用来将图像加载到我的gridview中,以便更好地加载/滚动.有人可以使用LruCache发布示例代码吗.提前致谢.
到目前为止,我在Android中使用SoftReference Cache来处理图像.此缓存用于ListView中显示的图像,如果有足够的内存,应该有助于保存内存中未显示的项目图像.
这个问题是SoftReferences几乎是在最后一个硬引用发布的那一刻被垃圾收集的.结果是,从屏幕上移除的图像在那时被垃圾收集,并且如果用户在ListView中滚动回到该条目,则从内部电话存储器重新加载图像,导致复杂的延迟加载过程,从而导致频繁重绘列表和一般性能不佳.
软引用行为的错误请求表明这是预期的行为,您应该使用LRU-Cache来缓存此类内容.
知道我的问题.LRU缓存只会占用我允许的内存量.但如果应用程序需要大量内存,则无法释放内存.我应该如何确定我可以允许缓存使用多少内存,如果手机的内存情况变得紧张,有没有办法减少缓存的大小?
目前,图像缓存作为一种用于所有活动的全局图像存储保存在应用程序内.这将导致我的应用程序不断使用图像缓存的所有内存,即使我的活动在后台或被破坏.
我检查了LRUCache的官方Android文档,其中说:每次访问一个值时,它都会移动到队列的头部.将值添加到完整缓存时,该队列末尾的值将被逐出,并且可能符合垃圾回收的条件.我想这是双链表,它由缓存使用的linkedhashmap维护.为了检查这种行为,我检查了LruCache的源代码,并检查了get(K key)方法.它进一步调用map的get方法,该方法从底层hashmap获取值并调用recordAccess方法.
public V get(Object key) {
LinkedHashMapEntry<K,V> e = (LinkedHashMapEntry<K,V>)getEntry(key);
if (e == null)
return null;
e.recordAccess(this);
return e.value;
}
Run Code Online (Sandbox Code Playgroud)
如果accessOrder设置为true(对于我的问题,我们假设它是),recordAccess方法依次将访问的条目移动到列表的末尾,否则它什么都不做.
/**
* This method is invoked by the superclass whenever the value
* of a pre-existing entry is read by Map.get or modified by Map.set.
* If the enclosing Map is access-ordered, it moves the entry
* to the end of the list; otherwise, it does nothing.
*/
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm …
Run Code Online (Sandbox Code Playgroud) final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.getByteCount() / 1024;
}
};
URL url = new URL("http://s2.goodfon.ru/image/260463-1920x1200.jpg");
Bitmap bitmap = BitmapFactory.decodeStream((InputStream) url.getContent(), null, options);
if(bitmap != null)
Log.i("Success", "BITMAP IS NOT NULL");
String key = "myKey";
Log.i("Get is null", "putting myKey");
mMemoryCache.put(key, …
Run Code Online (Sandbox Code Playgroud) 我在我的应用程序中使用bitmapfun项目(gridview),而我在测试这个时发现了一个问题.重现此问题的步骤如下:
在logcat中,我看到所有图像都在imageWorker的cancelPotentialWork()中被取消,它们永远不会启动.我的猜测是,之前的bitmapworkerTask(负责下载)发生了一些事情,并且与新任务发生冲突.在我的应用程序按下后退按钮时,我清除所有缓存.但这不是问题的原因,因为我也测试了原始bitmapfun中的相同场景,问题也出现了!我该如何解决这个问题?我还将项目的多线程asynctask更改为单个线程!有没有办法清除所有imageview引用并取消所有正在运行的任务?
对不起我的英语,并且没有提供有关bitmapfun项目性质的更多信息,但它会非常扩展我的问题!向我提问!
编辑:为了重现问题,每次使用菜单选项离开活动时,最好清除缓存.如果您按照步骤1-3进行一次,也不确定是否会出现此问题.也许你必须重复它们!
Edit2(附加帮助):当我开始没有问题的活动时,第一个图像的logcat如下:
04-24 02:31:56.400: D/ImageWorker(25625): doInBackground - starting work
04-24 02:31:56.400: D/ImageFetcher(25625): processBitmap - https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s160-c/Antelope%252520Butte.jpg
04-24 02:31:56.400: D/ImageFetcher(25625): processBitmap, not found in http cache, downloading...
Run Code Online (Sandbox Code Playgroud)
当我开始有问题的活动时,logcat是这样的:
04-24 02:28:07.970: D/ImageWorker(24014): cancelPotentialWork - cancelled work for https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s160-c/Antelope%252520Butte.jpg
Run Code Online (Sandbox Code Playgroud)
为什么在第二种情况下调用cancelPotentialWork时doInBackground永远不会启动?根据代码序列,这是应该执行的下一个部分!至少有任何人想知道我应该在哪里搜索错误吗?
我正在尝试遵循关于 LruCache 使用的 2 年前的 android 教程,到目前为止我在谷歌上搜索的一些示例具有相同的方法,即传递一个转换为 KiB 的值(int)。
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8; //use 1/8th of what is available
imageCache = new LruCache<>(cacheSize);
Run Code Online (Sandbox Code Playgroud)
但是,从 Google 的文档中获取,传递的 int 值似乎转换为字节(来自 MiB):https : //developer.android.com/reference/android/util/LruCache.html
int cacheSize = 4 * 1024 * 1024; // 4MiB
LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道哪个是正确的计量单位。任何答案将不胜感激..
我正在编写一个使用LruCache的项目,它包含在android-support-v4.jar compat库中.在使用JB的设备上运行时,代码运行正常,但是当我在带有GB的Droid X上运行它时,应用程序会因以下错误而死机:
I/dalvikvm(2459): Could not find method android.util.LruCache.put, referenced from method blah.blah.Utility.getBitmap
W/dalvikvm(2459): VFY: unable to resolve virtual method 2641: Landroid/util/LruCache;.put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
D/dalvikvm(2459): VFY: replacing opcode 0x6e at 0x0026
... [repeats similar lines] ...
W/dalvikvm(2459): Unable to resolve superclass of Lblah/blah/Utility$1; (353)
W/dalvikvm(2459): Link of class 'Lblah/blah/Utility$1;' failed
E/dalvikvm(2459): Could not find class 'blah.blah.Utility$1', referenced from method blah.blah.Utility.initCaches
W/dalvikvm(2459): VFY: unable to resolve new-instance 559 (Lblah/blah/Utility$1;) in Lblah/blah/Utility;
D/dalvikvm(2459): VFY: replacing opcode 0x22 at 0x000d
D/dalvikvm(2459): VFY: dead code …
Run Code Online (Sandbox Code Playgroud) android android-2.3-gingerbread android-lru-cache android-support-library
我在Android中实现了一个存储对象的标准LRUCache.每个键都是与存储的Object关联的唯一ObjectId.我的问题是从缓存中检索Object的唯一方法是ObjectId(没有迭代器).实现getAll()方法的最佳方法是什么?另一种选择是将所有ObjectIds存储在某个列表的列表中,因此我可以迭代列表并获取所有对象 - 但是保存所有ObjectIds的最佳方法是什么?
谢谢!
我使用从Android中的LruCache继承的自定义类时出错.它应该下载图像并缓存它们; 昨天,它正在运作,但今天早上我遇到了这个问题.
这是该类的代码:
public class LruMemoryCache extends LruCache<String, Bitmap> {
private final Context context;
private static LruMemoryCache instance;
private LruMemoryCache(Context context) {
// super(1024 * 1024 * (((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass()) / 8);
super(5 * 1024 * 1024);
this.context = context;
}
public static synchronized LruMemoryCache getInstance(Context context) {
if (instance == null) {
instance = new LruMemoryCache(context);
}
return instance;
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
public void loadBitmap(String url, ImageView imageView) {
final String …
Run Code Online (Sandbox Code Playgroud) 在Google Developer的API中有一个trimToSize()方法,我无法找到/使用它.如何清除或缩小LRU Cache的大小?
我一直在尝试在我的应用程序中实现LruCache,但我很难连接点和在不同组件之间传递位图.
我想知道如何在我的应用程序中集成LruCache.我也希望了解实施LruCache的过程,以便更多细节
第一个类是AsyncTask Image Loader,第二个类是我的自定义适配器
的AsyncTask
public class GetImagesBitmap extends AsyncTask<ImageView, Void, Bitmap>{
InputStream inputStream;
ImageView imageView = null;
String path;
@Override
protected Bitmap doInBackground(ImageView... imageViews) {
this.imageView = imageViews[0];
return download_Image((String)imageView.getTag());
}
@Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
private Bitmap download_Image(String url) {
final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse httpResponse = client.execute(httpGet);
final int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode
+ " while …
Run Code Online (Sandbox Code Playgroud)