我有一个简单的 ListActivity ,它显示了图像,我在ImageAdapter类的构造函数中为 Picasso Builder 提供了 OkHttpClient :
picassoClient = new OkHttpClient();
picassoClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain
.request()
.newBuilder()
.addHeader("Cookie","xyz")
.build();
return chain.proceed(newRequest);
}
});
new Picasso.Builder(context).downloader(new OkHttpDownloader(picassoClient)).build();
然后在getView()
我使用Picasso在ImageView中加载图像:
Picasso.with(context).load(xyzUrl).fit().centerCrop().into(vImage);
效果很好,但在设备的旋转中,我发现堆大小有时会慢慢增长,有时很快,有时会保持稳定。它很少掉落。我是在泄漏内存还是代码中有问题?
修改
我在Picasso的getView()
if (BuildConfig.DEBUG) {
Log.i("HEAP SIZE",
String.valueOf((Runtime.getRuntime().totalMemory() / 1024)
- (Runtime.getRuntime().freeMemory() / 1024)));
}
我发现在将位图加载到ImageView后,堆大小的增长发生在getView()
。
有什么问题?
编辑2 : 试图设置静态ImageAdapter,没有任何改变
编辑3:
尝试使用RecyclerView而不是ListView,行为相同:堆大小不断增长,同时滚动图像列表每onBindViewHolder()
步进30-40个字节。设备的旋转堆大小有时会增加甚至2-3兆字节。很少下降。
为什么堆大小缓慢但持续增长?为什么我会在设备旋转后泄漏一些缓存或一些缓存的位图?
更新
尝试了没有构造函数中的代码的适配器(没有new OkHttpClient
和new Picasso.Builder
),它可以工作, 堆大小现在保持稳定 。那么,使用cookie头管理初始化客户端的正确方法是什么?
结果是: 最后我创建了我的PicassoInstance类,它创建了一个独特的静态Picasso单例并将其设置为Picasso Library的单例。然后我在我的适配器构造函数
中设置它 PicassoInstance.setPicassoSingleton(context);
效果很好,这是我希望的正确方法。
public class PicassoInstance {
private static Picasso myPicassoInstance = null;
public static void setPicassoSingleton(Context context) {
if (myPicassoInstance == null) {
myPicassoInstance = createMyPicassoInstance(context);
Picasso.setSingletonInstance(myPicassoInstance);
if (BuildConfig.DEBUG) {
Log.i("PICASSO INSTANCE", "CREATED");
}
}
}
private static Picasso createMyPicassoInstance(Context context) {
OkHttpClient myOkHttpClient = new OkHttpClient();
myOkHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Cookie", "xyz").build();
if (BuildConfig.DEBUG) {
Log.i("ON INTERCEPT", "COOKIE ADDED");
}
return chain.proceed(newRequest);
}
});
return new Picasso.Builder(context).downloader(
new OkHttpDownloader(myOkHttpClient)).build();
}
}
答案 0 :(得分:3)
我无法将其视为过于宽泛,但我建议您took a memory dump并在Eclipse Memory Analizer Tool中仔细查看,以找出哪些引用仍然存在以及由谁执行。
适配器作为字段泄漏。视图包含包含视图的上下文。碎片甚至是更糟糕的罪犯。 ListActivities是一个应该在很久以前就已被弃用的API1工具。所有这些都非常容易泄漏,但那是Android方式。