列表适配器中的毕加索不从缓存加载图像

时间:2015-08-27 11:13:50

标签: android picasso

我正在使用毕加索从我的列表适配器中的服务器加载图像。当我上下滚动列表时Picasso会不断分配更多内存,屏幕如下: enter image description here

以下是我的列表适配器的一部分:

 @Override
    public View getView(final int position, View convertView, ViewGroup viewGroup) {
        ViewHolder viewHolder;

        if (convertView == null || convertView.getTag() == null) {
            //init list item
            viewHolder = new ViewHolder();

            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.subfood_item, viewGroup,
                    false);

            viewHolder.mImgvPicture = (ImageView) convertView.findViewById(R.id.imgvPicture);
            viewHolder.mTvHeader = (TextView) convertView.findViewById(R.id.tvHeader);
            viewHolder.mTvDescription = (TextView) convertView.findViewById(R.id.tvDescription);

            convertView.setTag(viewHolder);
        } else {
            //list item is used again - get all references for view
            viewHolder = (ViewHolder) convertView.getTag();
        }
        Product product = mItems.get(position);

        viewHolder.mTvHeader.setText(product.getName());
        viewHolder.mTvDescription.setText(product.getDescription());


        if (product.isAsset()) {
            String folderPath = "file:///android_asset/product/";
            Picasso.with(mContext).load(folderPath + product.getPath()).fit().centerCrop().
                    into(viewHolder.mImgvPicture);
        } else {
            RestUtils.loadImageWithPicasso(RestUtils.URL_IMAGE_FROM_PRODUCT + product.getNetId(), viewHolder.mImgvPicture);
        }


        return convertView;
    }

第一部分 - 从资产加载是好的。问题在于:

RestUtils.loadImageWithPicasso(RestUtils.URL_IMAGE_FROM_PRODUCT + product.getNetId(), viewHolder.mImgvPicture);

由于服务器身份验证和离线缓存,我使用其他方法将其包装起来。下面是RestUtils.loadImageWithPicasso的代码

 public static void loadImageWithPicasso(String url, ImageView imageView) {
        float dp = App.getContext().getResources().getDisplayMetrics().density;
        if(dp<=4.0f){
            url = url+"?size="+(int)Math.floor(dp);
        }  else {
            url = url+"?size=4";
        }

        String requestUrl = RestUtils.getUrl(url);

        OkHttpClient picassoClient = new OkHttpClient();

        final String finalUrl = url;
        String hash = RestUtils.getHashed(finalUrl);
        Interceptor interceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request newRequest = chain.request().newBuilder()
                        .addHeader(RestUtils.HEADER, RestUtils.getHashed(finalUrl))
                        .build();
                return chain.proceed(newRequest);
            }
        };

        picassoClient.interceptors().add(interceptor);

        File httpCacheDir = new File(App.getContext().getExternalCacheDir(), RestUtils.IMAGE_CACHE);
        long httpCacheSize = 40 * 1024 * 1024;
        Cache cache = new Cache(httpCacheDir, httpCacheSize);
        picassoClient.setCache(cache);

        Picasso picasso = new Picasso.Builder(App.getContext()).downloader(new OkHttpDownloader(picassoClient)).build();

        picasso.load(requestUrl)
                .into(imageView);
    }

即使我退出片段,仍然会分配内存。

1 个答案:

答案 0 :(得分:2)

不确定你能不能把毕加索归咎于此。您正在构建一个自定义Picasso实例,并在每个图像加载时使用新缓存。每次致电loadImageWithPicasso时,您的代码至少会分配以下新对象 - OkHttpClientInterceptorFileCachePicasso至少有两个String。您应该只构建一次Picasso实例。

有几种方法可以选择这样做。一个是 -

loadImageWithPicasso划分为两个方法createCustomPicasso,它们返回您的自定义毕加索对象,在您的UI代码中调用一次并保存在成员变量中。

然后,修改loadImageWithPicasso,这样就可以传入毕加索实例 -

public static void loadImageWithPicasso(Picasso picasso, String url, ImageView imageView) 

然后让它在发出请求之前执行特定于URL的修改。

最后一点,您的Interceptor应该从chain.getRequest()获取修改请求所需的数据,而不是使用其直接范围之外的数据。您在拦截器中引用finalUrl。它可以替换为chain.getRequest().urlString()有关使用情况的详细信息,请参阅interceptors上的文档。