我在使用从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 imageKey = url;
final Bitmap bitmap = get(imageKey);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(url);
}
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
Bitmap myBitmap;
ImageView mImageView;
public BitmapWorkerTask(ImageView imageView) {
mImageView = imageView;
}
@Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL("http://www.google.com/logos/classicplus.png");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
myBitmap = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
}
put(params[0], myBitmap);
return myBitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
mImageView.setImageBitmap(result);
}
}
}
这是LogCat的错误:
05-15 08:02:08.639: E/AndroidRuntime(12818): FATAL EXCEPTION: AsyncTask #2
05-15 08:02:08.639: E/AndroidRuntime(12818): java.lang.RuntimeException: An error occured while executing doInBackground()
05-15 08:02:08.639: E/AndroidRuntime(12818): at android.os.AsyncTask$3.done(AsyncTask.java:200)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.lang.Thread.run(Thread.java:1019)
05-15 08:02:08.639: E/AndroidRuntime(12818): Caused by: java.lang.NoSuchMethodError: getByteCount
05-15 08:02:08.639: E/AndroidRuntime(12818): at com.xs2theworld.sundio.caching.LruMemoryCache.sizeOf(LruMemoryCache.java:36)
05-15 08:02:08.639: E/AndroidRuntime(12818): at com.xs2theworld.sundio.caching.LruMemoryCache.sizeOf(LruMemoryCache.java:1)
05-15 08:02:08.639: E/AndroidRuntime(12818): at android.support.v4.util.LruCache.safeSizeOf(LruCache.java:230)
05-15 08:02:08.639: E/AndroidRuntime(12818): at android.support.v4.util.LruCache.put(LruCache.java:123)
05-15 08:02:08.639: E/AndroidRuntime(12818): at com.xs2theworld.sundio.caching.LruMemoryCache$BitmapWorkerTask.doInBackground(LruMemoryCache.java:72)
05-15 08:02:08.639: E/AndroidRuntime(12818): at com.xs2theworld.sundio.caching.LruMemoryCache$BitmapWorkerTask.doInBackground(LruMemoryCache.java:1)
05-15 08:02:08.639: E/AndroidRuntime(12818): at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-15 08:02:08.639: E/AndroidRuntime(12818): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
05-15 08:02:08.639: E/AndroidRuntime(12818): ... 4 more
知道为什么会这样吗?
非常感谢大家。
编辑:我刚刚意识到Google Galaxy Nexus S手机不会出现这种错误,但它与Samsun Galaxy一起发生..任何人都知道为什么?答案 0 :(得分:6)
问题是由以下原因造成的:
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
方法getByteCount()只能与API&gt; = 12一起使用,而三星Galaxy使用API 10。
解决方案:
@Override
protected int sizeOf(String key, Bitmap value) {
if (Integer.valueOf(android.os.Build.VERSION.SDK_INT) >= 12)
return value.getByteCount();
else
return (value.getRowBytes() * value.getHeight());
}
答案 1 :(得分:1)
对于LruCache,使用谷歌的支持库,或获取它的原始源代码。
通常,了解他们在源代码上所做的事情非常复杂,但这次很容易。
答案 2 :(得分:1)
我尝试了上述所有方法并且它们很接近,但不是很正确(至少对我的情况而言)。
我使用的是bitmap.getByteCount();创建新的LruCache时,在sizeOf()方法内部:
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount();
}
};
然后我尝试了建议:
return bitmap.getRowBytes() * bitmap.getHeight();
这很棒,但我注意到返回的值不同,当我使用上面的建议时,它甚至不会在我的设备上创建缓存。我测试了运行api 3.2的Nexus One和运行4.2的Galaxy Nexus的返回值:
bitmap.getByteCount(); returned-> 15
bitmap.getRowBytes() * bitmap.getHeight(); returned-> 15400
所以为了解决我的问题,我只是这样做了:
return (bitmap.getRowBytes() * bitmap.getHeight()) / 1000;
而不是:
return bitmap.getByteCount();
可能与你所处的情况不一样,但这对我有用。