Krø*_*lle 28 android out-of-memory picasso
我有RecyclerView几个图像使用Picasso.在向上和向下滚动一段时间后,应用程序内存不足,并显示如下消息:
E/dalvikvm-heap? Out of memory on a 3053072-byte allocation.
I/dalvikvm? "Picasso-/wp-content/uploads/2013/12/DSC_0972Small.jpg" prio=5 tid=19 RUNNABLE
I/dalvikvm? | group="main" sCount=0 dsCount=0 obj=0x42822a50 self=0x59898998
I/dalvikvm? | sysTid=25347 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1500612752
I/dalvikvm? | state=R schedstat=( 10373925093 843291977 45448 ) utm=880 stm=157 core=3
I/dalvikvm? at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
I/dalvikvm? at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
I/dalvikvm? at com.squareup.picasso.BitmapHunter.decodeStream(BitmapHunter.java:142)
I/dalvikvm? at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:217)
I/dalvikvm? at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:159)
I/dalvikvm? at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390)
I/dalvikvm? at java.util.concurrent.FutureTask.run(FutureTask.java:234)
I/dalvikvm? at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
I/dalvikvm? at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
I/dalvikvm? at java.lang.Thread.run(Thread.java:841)
I/dalvikvm? at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:411)
I/dalvikvm? [ 08-10 18:48:35.519 25218:25347 D/skia ]
--- decoder->decode returned false
Run Code Online (Sandbox Code Playgroud)
调试时我注意到的事情:
这是一个示例图像.它非常大,但我fit()用来减少应用程序中的内存占用.
所以我的问题是:
在创建时设置静态Picasso实例Activity:
private void setupPicasso()
{
Cache diskCache = new Cache(getDir("foo", Context.MODE_PRIVATE), 100000000);
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setCache(diskCache);
Picasso picasso = new Picasso.Builder(this)
.memoryCache(new LruCache(100000000)) // Maybe something fishy here?
.downloader(new OkHttpDownloader(okHttpClient))
.build();
picasso.setIndicatorsEnabled(true); // For debugging
Picasso.setSingletonInstance(picasso);
}
Run Code Online (Sandbox Code Playgroud)
在我的使用静态Picasso实例RecyclerView.Adapter:
@Override
public void onBindViewHolder(RecipeViewHolder recipeViewHolder, int position)
{
Picasso.with(mMiasMatActivity)
.load(mRecipes.getImage(position))
.placeholder(R.drawable.picasso_placeholder)
.fit()
.centerCrop()
.into(recipeViewHolder.recipeImage); // recipeImage is an ImageView
// More...
}
Run Code Online (Sandbox Code Playgroud)
在ImageViewXML文件中:
<ImageView
android:id="@+id/mm_recipe_item_recipe_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:paddingBottom="2dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:clickable="true"
/>
Run Code Online (Sandbox Code Playgroud)
似乎RecyclerView连续滚动会使内存分配无限增加.我做了一个测试RecyclerView剥离以匹配官方文档,使用单个图像200 CardView秒ImageView,但问题仍然存在.大多数图像都是从内存中加载的(绿色),滚动是平滑的,但大约每十分钟ImageView加载一次来自磁盘的图像(蓝色).从磁盘加载映像时,将执行内存分配,从而增加堆上的分配,从而增加堆本身的分配.
我尝试删除自己的全局Picasso实例设置并使用默认设置,但问题是相同的.
我使用Android设备监视器进行了检查,请参见下图.这是一个Galaxy S3.从磁盘加载图像时完成的每个分配都可以在"每个大小的分配计数"下的右侧看到.每个图像分配的大小略有不同,这也很奇怪.按"原因GB"使最右边的4.7 MB分配消失.
虚拟设备的行为是相同的.下图显示了Nexus 5 AVD.此外,当按下"原因GB"时,最大的分配(10.6 MB的分配)消失了.
此外,这里是内存分配位置和Android设备监视器中的线程的图像.重新发生的分配在Picasso线程中完成,而删除的分配Cause GB在主线程上完成.
Sam*_*ski 38
我不确定是否fit()合作android:adjustViewBounds="true".根据过去的一些问题,它似乎有问题.
一些建议:
resize()方法.memoryCache(new LruCache(100000000)) // Maybe something fishy here?
Run Code Online (Sandbox Code Playgroud)
我会说这确实很可疑 - 你给的是LruCache100MB的空间.虽然所有设备都是不同的,但是对于某些设备来说,这将达到或超过限制,请记住,这只是LruCache应用程序其余部分需要的堆空间.我的猜测是,这是异常的直接原因 - 你告诉LruCache它允许它变得比它应该大得多.
我会将其减少到5MB左右,以首先证明理论,然后在目标设备上逐步实验更高的值.您还可以查询设备的空间大小,并根据需要以编程方式设置此值.最后,android:largeHeap="true"你可以添加到你的清单中的属性,但我收集这通常是不好的做法.
你的图像确实很大,所以我建议减少它们.请记住,即使你正在修剪它们,它们仍然需要以其全尺寸暂时加载到内存中.
| 归档时间: |
|
| 查看次数: |
23850 次 |
| 最近记录: |