【发布时间】:2015-07-03 14:40:04
【问题描述】:
我有一个显示图像的简单 ListActivity,我在 ImageAdapter 类的构造函数中为 Picasso Builder 初始化了我的 OkHttpClient: p>
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()我用毕加索在ImageView中加载图片:
Picasso.with(context).load(xyzUrl).fit().centerCrop().into(vImage);
它运作良好,但在设备的轮换中,我看到 堆大小 有时会缓慢增长,有时会快速增长,有时会保持稳定。只是很少会掉落。我是在泄漏内存还是代码有问题?
编辑:
我在getView()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 MB。很少掉落。
为什么堆大小缓慢但持续增长,为什么我会在设备旋转后泄漏一些缓存或一些缓存的位图?
更新:
尝试了没有构造函数中代码的适配器(即没有 new OkHttpClient 和 new Picasso.Builder),它可以工作并且堆大小现在下降得很好,保持稳定。那么,用cookie头管理初始化客户端的正确方法是什么?
简明扼要: 最后我创建了我的 PicassoInstance 类,它创建了一个独特的静态毕加索单例并将其设置为毕加索图书馆的单例。然后我在我的适配器构造函数中设置它
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();
}
}
【问题讨论】:
-
请展示你的生命周期方法。
-
所以你每次都在 onCreate() 中创建一个新的适配器?
-
那我猜适配器泄漏了一些东西。我在 onPause() 中明确地将其设为空,有什么变化吗?如果没有,可能值得显示您的适配器代码。您是否将其绑定到其他任何东西?
-
毕加索将图像缓存在内存中以便快速检索,所以我的猜测是它只是保留对图像的引用,直到感觉需要删除它们。在您产生 OOM 错误之前,我不会担心它。
-
跟踪内存分配的最简单方法是使用 android 的 MAT 实用程序。它给出了未从内存中释放的类对象的列表。你可以在这里阅读它的用法:android-developers.blogspot.in/2011/03/…
标签: android android-recyclerview listadapter picasso okhttp