2012-05-15 2 views
4

У меня возникла ошибка с использованием пользовательского класса, который наследуется от LruCache в Android. Предполагается загрузить изображения и кешировать их; вчера он работал, но сегодня утром я столкнулся с этой проблемой.NoSuchMethodError с помощью LruCache в Android

Это код класса:

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 

Любая идея, почему это могло произойти?

Большое спасибо всем.

EDIT: Я только понял, что эта ошибка не происходит с телефоном Google Galaxy Nexus S, но это происходит с галактикой Самсун .. кто-нибудь знает почему?

+0

как вы решить этот вопрос, как я все еще получаю ошибку компиляции времени на 'getByteCount()' – Hunt

+0

@Hunt проверить мой комментарий ниже, принятый ответ – noloman

ответ

6

Проблема вызвана:

@Override 
    protected int sizeOf(String key, Bitmap value) { 
     return value.getByteCount(); 
    } 

Метод getByteCount() может быть использована только с API> = 12, а Samsung 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

для LruCache, используйте библиотеку поддержки google или получите исходный код.

Обычно довольно сложно понять, что они сделали с исходным кодом, но на этот раз это довольно просто.

+0

я уже с помощью SupportLibrary – noloman

+0

я вижу, так что вы должны код андроида. вот что-то, что сработало для меня после нескольких настроек (измените часть map.eldest()): http: // www.oschina.net/code/explore/android-4.0.1/core/java/android/util/LruCache.java –

+0

<... вы должны проверить код ...> –

1

Я пробовал все вышеперечисленные методы, и они были близки, но не совсем корректны (по крайней мере для моей ситуации).

Я использовал bitmap.getByteCount(); внутри метода SizeOf() при создании нового LruCache:

mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
    @Override 
    protected int sizeOf(String key, Bitmap bitmap) { 
     return bitmap.getByteCount(); 
    } 
}; 

Затем я попытался предложил:

return bitmap.getRowBytes() * bitmap.getHeight(); 

Это было здорово, но я заметил, что возвращаемые значения были разные, и, когда я предложение выше, оно даже не сделает кеш на моем устройстве. Я проверял возвращаемые значения на Nexus один погонный API 3.2 и Galaxy Nexus работает 4.2:

bitmap.getByteCount(); returned-> 15 
bitmap.getRowBytes() * bitmap.getHeight(); returned-> 15400 

Так, чтобы решить мою проблему, я просто сделал это:

return (bitmap.getRowBytes() * bitmap.getHeight())/1000; 

вместо:

return bitmap.getByteCount(); 

Не может быть такой же ситуации, в которой вы были, но это сработало для меня.

+0

везде я смотрю, каждый источник, который я читаю, все, что я вижу, это return (bitmap.getRowBytes() * bitmap.getHeight())/1000; '. Это должен быть тип файла, который я сохраняю или что-то в этом роде. Поэтому в следующий раз мне нужно использовать 'bitmap.getByteCount();', я сделаю некоторое тестирование, чтобы узнать, какое значение мне нужно в первую очередь. – levibostian