我正在使用毕加索从我的列表适配器中的服务器加载图像。当我上下滚动列表时Picasso会不断分配更多内存,屏幕如下:
以下是我的列表适配器的一部分:
@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);
}
即使我退出片段,仍然会分配内存。
答案 0 :(得分:2)
不确定你能不能把毕加索归咎于此。您正在构建一个自定义Picasso
实例,并在每个图像加载时使用新缓存。每次致电loadImageWithPicasso
时,您的代码至少会分配以下新对象 - OkHttpClient
,Interceptor
,File
,Cache
,Picasso
至少有两个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上的文档。