2013-08-21 70 views
1

我一直試圖在我的應用程序中實現LruCache,但在連接點和傳遞位圖之間不同組件之間存在困難。使用LruCache在內存中存儲位圖

我想知道如何將LruCache集成到我的應用程序中。我也看明白了實施LruCache讓更多細節越好

第一類是的AsyncTask圖像裝載機和第二類的過程是我的自定義適配器

的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 retrieving bitmap from " + url); 
       return null; 
      } 

      final HttpEntity entity = httpResponse.getEntity(); 
      if(entity != null){ 
       inputStream = null; 
       inputStream = entity.getContent(); 
       final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
       return bitmap; 
      } 
       if(inputStream != null){ 
        inputStream.close(); 
       } 
       entity.consumeContent(); 

     } catch (IOException e) { 

      httpGet.abort(); 
      Log.w("ImageDownloader", "Error while retrieving bitmap from " + url); 
     }finally{ 
      if(client != null){ 
       client.close(); 
      } 
     } 

     return null; 
     } 



    } 

自定義視圖適配器類

public class CustomListingListAdapter extends ArrayAdapter<HashMap<String, String>> { 





    private ArrayList<HashMap<String, String>> data; 
    private Context context; 
    private LayoutInflater mInflater; 
    private int viewId; 
    private String[] tag; 
    HashMap<String, String> currentData = new HashMap<String, String>(); 

    //private static final String TAG_CONTENT = "content"; 
    //private static final String TAG_RATING = "rating"; 
    private static final String TAG_NAME = "name"; 
    private static final String TAG_IMAGE_PATH = "image_path"; 
    private static final String TAG_PRODUCT_ID = "product_id"; 
    private static final String TAG_RATING = "rating"; 

    public CustomListingListAdapter(Context c, 
      ArrayList<HashMap<String, String>> data, 
      int viewId, String[] tag) { 
     super(c, viewId, data); 

     this.context = c; 
     this.data= data; 
     this.viewId = viewId ; 
    } 

    @Override 
    public int getCount() { 

     return data.size(); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     View vi = convertView; 
     Holder holder; 

     if (convertView == null) { 

      // Inflate the view since it does not exist 
      if (vi == null) { 
       mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       vi = mInflater.inflate(R.layout.list_item_layout, null); 

      } 

      holder = new Holder(); 

      holder.Name = (TextView) vi.findViewById(R.id.name); 
      holder.pid = (TextView) vi.findViewById(R.id.pid); 
      holder.imageView = (ImageView) vi.findViewById(R.id.list_image); 
      holder.ratingView = (ImageView) vi.findViewById(R.id.num_stars); 

      vi.setTag(holder); 
     }else { 
      holder = (Holder) vi.getTag(); 
     } 


     currentData = (HashMap<String, String>) data.get(position); 
     holder.imageView.setTag(currentData.get(TAG_IMAGE_PATH)); 





     if (currentData != null) { 

      holder.Name.setText(currentData.get(TAG_NAME)); 
      holder.pid.setText(currentData.get(TAG_PRODUCT_ID)); 
     } 

     new GetImagesBitmap().execute(holder.imageView); 
    return vi; 


    } 
    private static class Holder { 

     public ImageView imageView; 
     public ImageView ratingView; 
     public TextView pid; 
     public TextView Name; 

     } 
    } 

回答

5

您在正確的軌道上,但我無法分辨您的代碼中您認爲在哪裏查看recyclin g在List/GridView中。你確實重用了傳遞給getView的convertView,但是在每個getView中啓動一個新的AsyncTask將導致加載圖像的任務,但如果它啓動的視圖被回收,則將它們插入到錯誤的列表行中。我的建議是查看Google的新網絡庫Volley。它有一個NetworkImageView類,可以將圖像異步加載到ImageView中。我推薦它的原因是緩存,無論是在磁盤上還是在內存中,視圖回收都是爲你處理的。

亂射: https://developers.google.com/events/io/sessions/325304728

如果你想解決這個你自己,我想看看在Android開發者博客帖子大約在ListView加載位圖。它演示了像您想要的那樣使用AsyncTasks,但它正確地處理了視圖回收。

文章: http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

最後一點提示:不要實例化一個新的HttpClient每個網絡通話。創建一個需要一些時間,首選的方法是將一個配置爲多線程的HttpClient作爲Singleton實例保留,並將其用於網絡調用。或者,您可以爲每個請求創建一個新的HttpUrlConnection;那對那個班來說沒問題。

編輯:對不起,我剛剛意識到我沒有真正回答這個問題。要爲Bimaps實現LruCache,您可以通過一些調整來從支持庫中擴展LruCache類。下面是我用於緩存Bitamps的類,用於Volley庫:

// From com.android.volley.toolbox.ImageLoader 
public interface ImageCache { 
    public Bitmap getBitmap(String url); 
    public void putBitmap(String url, Bitmap bitmap); 
} 

// My ImageCache implementation 
public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageCache { 
    private static final int DEFAULT_CACHE_SIZE = (int) (Runtime.getRuntime().maxMemory()/1024)/8; 

    public BitmapLruCache() { 
     this(DEFAULT_CACHE_SIZE); 
    } 

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

    @Override 
    public Bitmap getBitmap(String url) { 
     return get(url); 
    } 

    @Override 
    public void putBitmap(String url, Bitmap bitmap) { 
     put(url, bitmap); 
    } 

    @Override 
    protected int sizeOf(String key, Bitmap value) { 
     return value == null ? 0 : value.getRowBytes() * value.getHeight()/1024; 
    } 
} 
+0

謝謝,我會盡量使用它並學習,因爲我去。 – user2510952

+0

我確實在凌空觀看視頻,很棒的工具 – user2510952

+0

Volley還在積極發展中嗎?它尚未集成到開發人員文檔中,甚至沒有Gradle回購讓它在您的Android項目中使用。 –