2013-08-21 20 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项目中使用。 –