我需要将drawable文件夹中的一堆图像加载到imageview列表中。我得到一个java.lang.OutOfMemoryError:无法分配17280012字节分配8452164个空闲字节和8MB直到OOM错误。
这是一个数组文件,列出了需要加载的drawable文件夹中的所有图像名称。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="photo_frames">
<item>pf1</item>
<item>pf2</item>
<item>pf3</item>
<item>pf4</item>
<item>pf5</item>
<item>pf6</item>
<item>pf7</item>
<item>pf8</item>
<item>pf9</item>
<item>pf10</item>
<item>pf11</item>
<item>pf12</item>
</string-array>
</resources>
这是listAdapter加载图片的代码,photoFrames是一个包含图片名称的数组。
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
//Layout inflate for list item
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_photo_frames, null);
}
ImageView imgPhotoFrames = (ImageView) convertView.findViewById(R.id.image_photo_frames);
imgPhotoFrames.setImageResource(mContext.getResources().getIdentifier(photoFrames[position], "drawable", mContext.getPackageName()));
return convertView;
}
如果我有一些图像,它可以很好地加载,但它有点滞后。当有更多图像要加载到imageView时,它会返回错误,谢谢。
答案 0 :(得分:4)
17280012字节相当于2078 x 2078像素图像。 这大于大多数设备屏幕的分辨率。您应该一次加载0到1张这些图像,而不是12张。
如果您的图像具有这样的高分辨率,请降低其分辨率。
如果您的图片已经具有较低的分辨率,但是您将它们放在res/drawable/
中,请将它们移至res/drawable-nodpi/
或计划为不同的密度创建不同版本的drawable。 res/drawable/
中没有位图,因为它只是res/drawable-mdpi/
的同义词,因此Android会在更高密度的屏幕上对图像进行重新取样。
答案 1 :(得分:2)
你可以使用一个id的数组用于drawables
TypedArray
要加载它们,您可以使用// load array into CONSTRUCTOR
TypedArray photoFrameArray = getResources().obtainTypedArray(R.array.photo_frames);
// or set you ImageView's resource to the id
imgPhotoFrames.setImageResource(photoFrameArray.getResourceId(position, R.drawable.default_drawable));
photoFrameArray.recycle();
请记住,您应该回收数组
Picasso
此外,如果您的图像非常大(1000x1000像素),则会出现内存问题
为了加载大图片,我建议您使用ImageView
。您可以将大型drawable加载到cordova build -d
答案 2 :(得分:0)
这取决于您的Imageis有多大,当您在计算机上阅读尺寸时,Android似乎会分配比图像大小更多的空间。所以......
也许对你而言,这些想法的组合将起作用。
答案 3 :(得分:0)
您也可以使用缓存机制。
这是一个可以让您了解使用图片缓存的示例:
public class FlowerAdapter extends ArrayAdapter<Flower> {
private Context context;
private List<Flower> flowerList;
//set the LRU (Least Recently Used) object as an image cache
private LruCache<Integer,Bitmap> imageCache;
public FlowerAdapter(Context context, int resource, List<Flower> objects) {
super(context, resource, objects);
this.context = context;
this.flowerList = objects;
//initialize the cache in the constructor
//determine the maximum amount of memory of the device
final int maxMemory = (int) (Runtime.getRuntime().maxMemory());
//set the cache size to be one-eight of the maximum memory
// final int cacheSize = maxMemory/9999999; //using this number you can see the effects
final int cacheSize = maxMemory/8; //real-life situation
//create the image cache (instantiate it)
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.item_flower, parent, false);
//Display flower name in the TextView widget
Flower flower = flowerList.get(position);
TextView tv = (TextView) view.findViewById(R.id.textView1);
tv.setText(flower.getName());
//Display flower photo in ImageView widget
//verify if the flower exists in cache
Bitmap bitmap = imageCache.get(flower.getProductId());
if (bitmap != null) {
ImageView image = (ImageView) view.findViewById(R.id.imageView1);
image.setImageBitmap(bitmap);
}
else {
FlowerAndView container = new FlowerAndView();
container.flower = flower;
container.view = view;
ImageLoader loader = new ImageLoader();
loader.execute(container);
}
return view;
}
class FlowerAndView {
public Flower flower;
public View view;
public Bitmap bitmap;
}
private class ImageLoader extends AsyncTask<FlowerAndView, Void, FlowerAndView> {
@Override
protected FlowerAndView doInBackground(FlowerAndView... params) {
FlowerAndView container = params[0];
Flower flower = container.flower;
try {
String imageUrl = MainActivity.PHOTOS_BASE_URL + flower.getPhoto();
InputStream in = (InputStream) new URL(imageUrl).getContent();
Bitmap bitmap = BitmapFactory.decodeStream(in);
flower.setBitmap(bitmap);
in.close();
container.bitmap = bitmap;
return container;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(FlowerAndView result) {
ImageView image = (ImageView) result.view.findViewById(R.id.imageView1);
image.setImageBitmap(result.bitmap);
// result.flower.setBitmap(result.bitmap);
//put the image in the cache
imageCache.put(result.flower.getProductId(),result.bitmap);
}
}
}