Java Android网格图像视图会消耗所有内存并崩溃
我正在尝试调试我的应用程序中消耗所有内存并导致应用程序崩溃的位置 它全部加载查找,但当我向下滚动网格视图时,我将更多图像加载到网格视图所有ok。如果我向上滚动,我可以看到它们正在从缓存加载。但当我不断向下滚动时,设备分配了大约250mb的内存并崩溃了。知道我哪里出错了吗 我还应该注意到,这个网格在崩溃时有大约150个图像(每个约20kb)。我希望得到更多 请对我温柔一点,我是Java和Android新手 项目适配器Java Android网格图像视图会消耗所有内存并崩溃,java,android,out-of-memory,Java,Android,Out Of Memory,我正在尝试调试我的应用程序中消耗所有内存并导致应用程序崩溃的位置 它全部加载查找,但当我向下滚动网格视图时,我将更多图像加载到网格视图所有ok。如果我向上滚动,我可以看到它们正在从缓存加载。但当我不断向下滚动时,设备分配了大约250mb的内存并崩溃了。知道我哪里出错了吗 我还应该注意到,这个网格在崩溃时有大约150个图像(每个约20kb)。我希望得到更多 请对我温柔一点,我是Java和Android新手 项目适配器 public ItemAdapter(Context context, int
public ItemAdapter(Context context, int resource, List<Item> objects) {
super(context, resource, objects);
this.context = context;
this.itemList = objects;
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
imageCache = new LruCache<>(cacheSize);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.feed_staggered_grid_view_item, parent, false);
//Display item name in textview widget
Item item = itemList.get(position);
TextView item_title = (TextView) view.findViewById(R.id.textView1);
item_title.setText(item.getTitle());
TextView item_brand = (TextView) view.findViewById(R.id.textView2);
item_brand.setText(item.getBrand());
//display image
Bitmap bitmap = imageCache.get(item.getItemId());
if (bitmap != null) {
ImageView image = (ImageView) view.findViewById(R.id.imageView);
image.setImageBitmap(bitmap);
} else {
ItemAndView container = new ItemAndView();
container.item = item;
container.view = view;
ImageLoader loader = new ImageLoader();
loader.execute(container);
}
return view;
}
class ItemAndView {
public Item item;
public View view;
public Bitmap bitmap;
}
private class ImageLoader extends AsyncTask<ItemAndView, Void, ItemAndView> {
@Override
protected ItemAndView doInBackground(ItemAndView... params) {
ItemAndView container = params[0];
Item item = container.item;
try {
StringBuilder sb = new StringBuilder();
sb.append(FeedFragment.IMAGES_BASE_URL);
sb.append(item.getCategory());
sb.append("/");
sb.append(item.getProductId());
sb.append("/img1.jpg");
String imageUrl = sb.toString();
InputStream in = (InputStream) new URL(imageUrl).getContent();
Bitmap bitmap = BitmapFactory.decodeStream(in);
item.setBitmap(bitmap);
in.close();
container.bitmap = bitmap;
return container;
} catch (Exception e){
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ItemAndView itemAndView) {
ImageView image = (ImageView) itemAndView.view.findViewById(R.id.imageView);
image.setImageBitmap(itemAndView.bitmap);
if (imageCache.get(itemAndView.item.getItemId()) == null) {
imageCache.put(itemAndView.item.getItemId(), itemAndView.bitmap);
}
}
}
尝试使用convertView,而不是为每个调用创建视图。在getView中的前两行代码中尝试以下代码:
这里的问题是加载的位图太大。不仅下载图像,而且放置也应该在后台完成。使用AsyncTask来完成此任务,也可以始终使用或。我有同样的问题,并解决了它使用离子,工作得很好
此外,不要为每个项目加载一个不同的视图,请使用convertView。我认为您需要转到mainfiest文件,并在应用程序标记上添加以下行:
android:largeHeap="true"
如果加载速度太快,请尝试在启动太多图像加载过程之间添加一些时间。请注意,您提供的这段代码会立即开始加载所有代码。@user968808请检查这段代码。。它可能对适配器类有所帮助,这在一定程度上有所帮助。如中所示,我可以看到内存实际上减少了几倍,但仍然会因相同的错误而崩溃,并导致网格上的奇怪行为,随着我向下滚动图像的变化。我已经添加了Fragment类,以防对任何人都有帮助。谢谢,我会尝试的。20kb的图像是否太大?我的目标尺寸是多少?很高兴能帮上忙。图像没有固定的完美大小,因为它取决于加载的量。无论如何,你不应该让用户为这些加载付费,这样在加载过程中设备会变慢。因此,您应该以一种方式来管理它们,让它们在后台缓慢地加载(不是一次加载全部),这些库为您这样做:Dno,避免这种情况。这个选项(根据谷歌的说法)应该是你最后的选择。更大的堆将生成更长的GC。
FATAL EXCEPTION: AsyncTask #5
Process: com.test.game.test, PID: 10931
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 429212 byte allocation with 80604 free bytes and 78KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:635)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:611)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:649)
at com.test.game.adapters.ItemAdapter$ImageLoader.doInBackground(ItemAdapter.java:106)
at com.test.game.adapters.ItemAdapter$ImageLoader.doInBackground(ItemAdapter.java:89)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
View view;
if (convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.feed_staggered_grid_view_item, parent, false);
}else{
view = convertView;
}
android:largeHeap="true"