2012-07-24 13 views
30

アンドロイドLruCacheを理解するのに役立つ必要があります。私はロード/スクロールをより良くするために、画像を私のgridviewにロードするのに使いたい。誰かがLruCacheを使ってサンプルコードを投稿できますか?前もって感謝します。Androids lrucacheを使用した例

答えて

32

は、これは、プレゼンテーションDoing More With Less: Being a Good Android Citizen given at Google I/O 2012に基づいており、私はLruCacheを使用してのために作られたクラスです。

私はTCImageLoaderクラスでやっているの詳細については、映画をチェックアウト:

public class TCImageLoader implements ComponentCallbacks2 { 
    private TCLruCache cache; 

    public TCImageLoader(Context context) { 
     ActivityManager am = (ActivityManager) context.getSystemService(
      Context.ACTIVITY_SERVICE); 
     int maxKb = am.getMemoryClass() * 1024; 
     int limitKb = maxKb/8; // 1/8th of total ram 
     cache = new TCLruCache(limitKb); 
    } 

    public void display(String url, ImageView imageview, int defaultresource) { 
     imageview.setImageResource(defaultresource); 
     Bitmap image = cache.get(url); 
     if (image != null) { 
      imageview.setImageBitmap(image); 
     } 
     else { 
      new SetImageTask(imageview).execute(url); 
     } 
    } 

    private class TCLruCache extends LruCache<String, Bitmap> { 

     public TCLruCache(int maxSize) { 
      super(maxSize); 
     } 

     @Override 
     protected int sizeOf(ImagePoolKey key, Bitmap value) { 
      int kbOfBitmap = value.getByteCount()/1024; 
      return kbOfBitmap; 
     } 
    } 

    private class SetImageTask extends AsyncTask<String, Void, Integer> { 
     private ImageView imageview; 
     private Bitmap bmp; 

     public SetImageTask(ImageView imageview) { 
      this.imageview = imageview; 
     } 

     @Override 
     protected Integer doInBackground(String... params) { 
      String url = params[0]; 
      try { 
       bmp = getBitmapFromURL(url); 
       if (bmp != null) { 
        cache.put(url, bmp); 
       } 
       else { 
        return 0; 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
       return 0; 
      } 
      return 1; 
     } 

     @Override 
     protected void onPostExecute(Integer result) { 
      if (result == 1) { 
       imageview.setImageBitmap(bmp); 
      } 
      super.onPostExecute(result); 
     } 

     private Bitmap getBitmapFromURL(String src) { 
      try { 
       URL url = new URL(src); 
       HttpURLConnection connection 
        = (HttpURLConnection) url.openConnection(); 
       connection.setDoInput(true); 
       connection.connect(); 
       InputStream input = connection.getInputStream(); 
       Bitmap myBitmap = BitmapFactory.decodeStream(input); 
       return myBitmap; 
      } catch (IOException e) { 
       e.printStackTrace(); 
       return null; 
      } 
     } 

    } 

    @Override 
    public void onConfigurationChanged(Configuration newConfig) { 
    } 

    @Override 
    public void onLowMemory() { 
    } 

    @Override 
    public void onTrimMemory(int level) { 
     if (level >= TRIM_MEMORY_MODERATE) { 
      cache.evictAll(); 
     } 
     else if (level >= TRIM_MEMORY_BACKGROUND) { 
      cache.trimToSize(cache.size()/2); 
     } 
    } 
} 
+0

pre-honeycomb LruCacheまたはそれより新しいものに基づいていますか? http://developer.android.com/reference/android/support/v4/util/LruCache.htmlまたはhttp://developer.android.com/reference/android/util/LruCache.html – idish

+0

その推測はサポートされているtrimToSizeはAPI> 17でしか機能しないため、サポート版です。 –

14

Caching Bitmapsを参照してください。LruCacheの使用が実証されています。

次のようにページからコードの関連部分は次のとおりです。 - 以下

private LruCache mMemoryCache; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    // Get memory class of this device, exceeding this amount will throw an 
    // OutOfMemory exception. 
    final int memClass = ((ActivityManager) context.getSystemService(
      Context.ACTIVITY_SERVICE)).getMemoryClass(); 

    // Use 1/8th of the available memory for this memory cache. 
    final int cacheSize = 1024 * 1024 * memClass/8; 

    mMemoryCache = new LruCache(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in bytes rather than number of items. 
      return bitmap.getByteCount(); 
     } 
    }; 
    ... 
} 

public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 
    if (getBitmapFromMemCache(key) == null) { 
     mMemoryCache.put(key, bitmap); 
    } 
} 

public Bitmap getBitmapFromMemCache(String key) { 
    return mMemoryCache.get(key); 
} 
+0

に与えられたコードから取得されます。ジェネリック型LruCache への参照は、パラメータ化する必要があります。ここから私はLruCacheを拡張する必要があるように感じるこれはケースですか? – MobDev

+0

拡張する必要はありません。 'LruCache'は汎用クラスです。その意味を理解するためにJava Genericsを読んでください。 [Generic Types](http://docs.oracle.com/javase/tutorial/java/generics/types.html)のこのチュートリアルでは、この作業を開始する必要があります。 – Rajesh

+0

私はそれを今、感謝します。しかし、私はまだ正常にこのコードの作業を行うことができません – MobDev

18

私は私のために完璧に動作し、本当に簡単な方法を見つけた...

これをCache.javaクラスです。このクラスでは、静的getInstance()メソッドを使用することで、アプリケーション全体で1つのキャッシュインスタンスしか作成できません。 getLru()メソッドは、キャッシュされたオブジェクトを取得するために使用されますが、後でそれを使用する方法が示されます。このキャッシュは一般的なもので、オブジェクト型をオブジェクトに保存できます。

public void saveBitmapToCahche(){ 

     //The imageView that you want to save it's bitmap image resourse 
     ImageView imageView = (ImageView) findViewById(R.id.imageViewID); 

     //To get the bitmap from the imageView 
     Bitmap bitmap = ((BitmapDrawable)imageview.getDrawable()).getBitmap(); 

     //Saving bitmap to cache. it will later be retrieved using the bitmap_image key 
     Cache.getInstance().getLru().put("bitmap_image", bitmap); 
    } 

:これは、あなたがキャッシュにビットマップを保存し、あなたの活動のコードは

import android.support.v4.util.LruCache; 

public class Cache { 

    private static Cache instance; 
    private LruCache<Object, Object> lru; 

    private Cache() { 

     lru = new LruCache<Object, Object>(1024); 

    } 

    public static Cache getInstance() { 

     if (instance == null) { 

      instance = new Cache(); 
     } 

     return instance; 

    } 

    public LruCache<Object, Object> getLru() { 
     return lru; 
    } 
} 

:小さすぎる場合、ここで1024に設定されているキャッシュメモリのサイズは、それを変更することができますこれは、ビットマップをキャッシュから取得し、次にこのビットマップにimageViewを設定するコードです。

public void retrieveBitmapFromCache(){ 

     //The imageView that you want to set to the retrieved bitmap 
     ImageView imageView = (ImageView) findViewById(R.id.imageViewID); 

     //To get bitmap from cache using the key. Must cast retrieved cache Object to Bitmap 
     Bitmap bitmap = (Bitmap)Cache.getInstance().getLru().get("bitmap_image"); 

     //Setting imageView to retrieved bitmap from cache 
     imageView.setImageBitmap(bitmap)); 

} 

これはすべてです!ご覧のとおり、これは簡単で簡単です。

  • 例:彼らはクラスのすべてのメソッドが見ることができるので、自分のアプリケーションで

は、すべてのビューは、クラス変数に保存されます。最初のアクティビティでは、インテントを使用して新しいアクティビティを開始する直前に、onClickButton()メソッドでイメージビットマップをキャッシュに保存します。

public void onClickButton(View v){ 

    Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap(); 
    String name = textEdit.getText().toString(); 

    Cache.getInstance().getLru().put("bitmap_image", bitmap); 
    Cache.getInstance().getLru().put("name", name); 

    Intent i = new Intent(FirstActivity.this, SecondActivity.class); 
    startActivity(i); 
} 

次に、インテントを使用して2番目のアクティビティから3番目のアクティビティに移動します。最後のアクティビティでは、他のオブジェクトをキャッシュに保存してから、インテントを使用して最初のアクティビティに戻ります。最初のアクティビティに戻ると、onCreate()メソッドが開始されます。私のキャッシュは任意のビットマップ値または別々に任意の文字列値を持っている場合はその方法では、私は(私のアプリケーションのビジネスに基づいて)チェック:

public ImageView imageView; 
public EditText editText; 

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_first); 

     //...Other code... 

     //The imageView that you want to save it's bitmap image resourse 
     imageView = (ImageView) findViewById(R.id.imageViewID); 

     //The editText that I want to save it's text into cache 
     editText = (EditText)findViewById(R.id.editTextID); 

     if(Cache.getInstance().getLru().get("name")!=null){ 
      editText.setText(Cache.getInstance().getLru().get("name").toString()); 
     } 
     if(Cache.getInstance().getLru().get("bitmap_image")!=null){ 
      imageView.setImageBitmap((Bitmap)Cache.getInstance().getLru().get("bitmap_image")); 
     } 

     //...Other code... 
    } 
+0

シンプルでありがとうございました。 –

+0

私はこれが答えとしてマークされるべきだと思います!良い例と私はちょうどそれを使用しました。共有ありがとう! – Mohammad

+0

これは正解とマークする必要があります – GvSharma

0

https://techienotes.info/2015/08/28/caching-bitmaps-in-android-using-lrucache/

このリンクは、画像をロードするために有するサンプルアプリケーションを完全なプロジェクトを持っていますLruCacheを使用してGridviewに追加します。

このクラスは、LruCacheを使用し、まあ、私は私の活動でこれを入れてみましたが、最初のものはLruCacheが生タイプであるエラーのすべての種類があり、リンク

public class ImageAdapter extends BaseAdapter{ 
private String TAG = getClass().getSimpleName(); 
Context mContext; 
ArrayList<Uri> imageList; 

private LruCache<String, Bitmap> mLruCache; 

public ImageAdapter (Context context){ 
    mContext = context; 

    //Find out maximum memory available to application 
    //1024 is used because LruCache constructor takes int in kilobytes 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

    // Use 1/4th of the available memory for this memory cache. 
    final int cacheSize = maxMemory/4; 
    Log.d(TAG, "max memory " + maxMemory + " cache size " + cacheSize); 

    // LruCache takes key-value pair in constructor 
    // key is the string to refer bitmap 
    // value is the stored bitmap 
    mLruCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes 
      return bitmap.getByteCount()/1024; 
     } 
    }; 

    imageList = new ArrayList<Uri>(); 
    //Change this directory to where the images are stored 
    String imagesFolderPath = Environment.getExternalStorageDirectory().getPath()+"/backups/"; 

    File imageSrcDir = new File (imagesFolderPath); 
    // if directory not present, build it 
    if (!imageSrcDir.exists()){ 
     imageSrcDir.mkdirs(); 
    } 

    ArrayList<File> imagesInDir = getImagesFromDirectory(imageSrcDir); 

    for (File file: imagesInDir){ 
     // imageList will hold Uri of all images 
     imageList.add(Uri.fromFile(file)); 
    } 
} 

@Override 
public int getCount() { 
    return imageList.size(); 
} 

@Override 
public Object getItem(int position) { 
    return null; 
} 

@Override 
public long getItemId(int position) { 
    return 0; 
} 

/** 
* 
* @param position The position of the item within the 
*     adapter's data set of the item whose view we want. 
* @param convertView it is the view to be reused 
* @param parent The parent that this view will eventually be attached to 
* @return a View corresponding to the data at the specified position. 
*/ 
@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ImageView imageView; 
    Bitmap thumbnailImage = null; 
    if (convertView == null){ 
     imageView = new ImageView(mContext); 
     imageView.setLayoutParams(
       //150,150 is size of imageview to display image 
       new GridView.LayoutParams(150, 150)); 
     imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
    } 
    else { 
     imageView = (ImageView)convertView; 
    } 

    // Use the path as the key to LruCache 
    final String imageKey = imageList.get(position).toString(); 

    //thumbnailImage is fetched from LRU cache 
    thumbnailImage = getBitmapFromMemCache(imageKey); 

    if (thumbnailImage == null){ 
     // if asked thumbnail is not present it will be put into cache 
     BitmapWorkerTask task = new BitmapWorkerTask(imageView); 
     task.execute(imageKey); 
    } 

    imageView.setImageBitmap(thumbnailImage); 
    return imageView; 
} 

/** 
* This function returns the files from a directory 
* @param parentDirPath source directory in which images are located 
* @return list of Files 
*/ 
private ArrayList<File> getImagesFromDirectory (File parentDirPath){ 
    ArrayList <File> listOfImages = new ArrayList<File>(); 
    File [] fileArray = null; 

    if (parentDirPath.isDirectory()){//parentDirPath.exists() && 
     // && 
     // parentDirPath.canRead()){ 
     fileArray = parentDirPath.listFiles(); 
    } 

    if (fileArray == null){ 
     return listOfImages; // return empty list 
    } 

    for (File file: fileArray){ 
     if (file.isDirectory()){ 
      listOfImages.addAll(getImagesFromDirectory(file)); 
     } 
     else { 
      // Only JPEG and PNG formats are included 
      // for sake of simplicity 
      if (file.getName().endsWith("png") || 
        file.getName().endsWith("jpg")){ 
       listOfImages.add(file); 
      } 
     } 
    } 
    return listOfImages; 
} 

/** 
* This function will return the scaled version of original image. 
* Loading original images into thumbnail is wastage of computation 
* and hence we will take put scaled version. 
*/ 
private Bitmap getScaledImage (String imagePath){ 
    Bitmap bitmap = null; 
    Uri imageUri = Uri.parse (imagePath); 
    try{ 
     BitmapFactory.Options options = new BitmapFactory.Options(); 

     /** 
     * inSampleSize flag if set to a value > 1, 
     * requests the decoder to sub-sample the original image, 
     * returning a smaller image to save memory. 
     * This is a much faster operation as decoder just reads 
     * every n-th pixel from given image, and thus 
     * providing a smaller scaled image. 
     * 'n' is the value set in inSampleSize 
     * which would be a power of 2 which is downside 
     * of this technique. 
     */ 
     options.inSampleSize = 4; 

     options.inScaled = true; 

     InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri); 

     bitmap = BitmapFactory.decodeStream(inputStream, null, options); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 

    return bitmap; 
} 

public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 
    if (getBitmapFromMemCache(key) == null) { 
     mLruCache.put(key, bitmap); 
    } 
} 

public Bitmap getBitmapFromMemCache(String key) { 
    return mLruCache.get(key); 
} 

class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> { 

    private final WeakReference<ImageView> imageViewReference; 

    public BitmapWorkerTask(ImageView imageView) { 
     // Use a WeakReference to ensure the ImageView can be garbage collected 
     imageViewReference = new WeakReference<ImageView>(imageView); 
    } 

    @Override 
    protected Bitmap doInBackground(String... params) { 
     final Bitmap bitmap = getScaledImage(params[0]); 
     addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); 
     return bitmap; 
    } 

    // onPostExecute() sets the bitmap fetched by doInBackground(); 
    @Override 
    protected void onPostExecute(Bitmap bitmap) { 
     if (imageViewReference != null && bitmap != null) { 
      final ImageView imageView = (ImageView)imageViewReference.get(); 
      if (imageView != null) { 
       imageView.setImageBitmap(bitmap); 
      } 
     } 
    } 
} 
} 
関連する問題