问题
I'm having a problem.
I'm loading 9 drawables
into 9 imageViews
dynamically. (drawables
are different each time) The drawable id is stored in the object class so when I load this drawable I set the ImageRessource
to the imageView
by using imageView.setImageRessource(myObject.getRessourceId());
Everything is working fine but when the 9 drawables are loaded, I see on the Android Memory Monitor that the allocate memory reaches 80MB and I think this isn't normal... (Is it?)
I tried different things to solve it:
- Load the drawable with the library Picasso.
- Use
BitmapFactory.decodeResssource
to create a Bitmap and then setImageBitmap on the imageView.
With all the techniques I tried, it takes 80MB of allocated memory.
I tried using different image resolution so in ldpi (~30Ko/image) and in xhdpi (~87Ko/image) but it doesn't change anything for each image loaded it takes about 5MB of allocated memory...
So my question is : How can I reduce the allocated memory for thoses images?
Thank you in advance, I can give parts of code if it's necessary.
Regards
PS: The ImageViews
are created dynamically in the onCreate()
method.
回答1:
This is normal, the biggest enemy of your memory are images. Also note that images take more space in memory than on the disk. It is also normal that it takes long time to load. The solution is to only load as big image as it is seen and using caches to load them faster next time (you don't need to downsample again). Here is an article with a sample project with just that: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
回答2:
Thanks to the link of Bojan Kseneman, I reduces the allocated memory to 30Mb. I'm using this:
imageView.setImageBitmap(Util.decodeSampledBitmapFromResource(getResources(), id, 150, 150));
Util is a Utility class of my project
with those methods :
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
And
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
回答3:
Depending on the nature of the image, this can be ok, actually. The filesize with modern images does not necessarily relate to the size it will have in memory, due to the compression algorithms used. In memory, the supposedly small file is expanded into the actual bitmap data, which means more data will be occupied in RAM than on sd-card/disk.
However, the sources (as well as the images) would be helpful for further analysis.
You could also take a look at the images in some viewer, and try to identify how much RAM it occupies when being loaded in that viewer. You might be surprised about the size, such images occupy. That's why UIs with themes that rely heavily on images are so memory-eating.
来源:https://stackoverflow.com/questions/29728573/android-loading-drawable-into-imageview-taking-a-lot-of-memory