Androidのグリッドビューに非常に小さな画像(平均サイズは90kb)を読み込もうとしています。私は9以上の画像をロードするたびに、私はメモリの問題が発生しています。私は画像をより小さなサイズにスケーリングしようとしましたが、これはある程度までは機能しますが、画質がひどいため実際には真の解決策ではありません。Android OutOfMemoryErrorがGridViewのビットマップをロードするとき
コードが
private Context mContext;
private ArrayList<Bitmap> photos = new ArrayList<Bitmap>();
public Bitmap [] mThumbIds;
public ImageAdapter(Context c) {
mContext = c;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public Bitmap scaleBitmap(String imagePath) {
Bitmap resizedBitmap = null;
try {
int inWidth = 0;
int inHeight = 0;
InputStream in;
in = new FileInputStream(imagePath);
// decode image size (decode metadata only, not the whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
// decode full image pre-resized
in = new FileInputStream(imagePath);
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth/300, inHeight/300);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, 300, 300);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// resize bitmap
resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return resizedBitmap;
}
public void populateGrid() {
File sdDir = new File("mnt/sdcard/Pictures");
File[] sdDirFiles = sdDir.listFiles();
for(File singleFile : sdDirFiles) {
String filePath = singleFile.getAbsolutePath();
Bitmap bmp = scaleBitmap(filePath);
photos.add(bmp);
}
mThumbIds = photos.toArray(new Bitmap[(photos.size())]);
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageBitmap(mThumbIds[position]);
return imageView;
}
@Override
public int getCount() {
return mThumbIds.length;
}
}
ご回答いただきありがとうございます。ビットマップのリサイクルを試みましたが、リサイクルされたビットマップを使用しようとしているという例外が続いています。ビットマップをリサイクルする必要がある例をお勧めします。 – JoshDavies
ビットマップをリサイクルするのは難しいです。ビューにまだ接続されていないインスタンスのみをリサイクルするようにしてください。あなたはジンジャーブレッドでこれらの問題を経験していますか?それがGinberbreadでない場合、リサイクルに関する私の提案は助けになる可能性が低く、ビットマップを何らかの形で漏らしている可能性が高いです。漏洩した文脈はしばしばここでの犯人です。そのような場合は、ヒープトレースツールを使用すると、コンテキストが長時間にわたって有効かどうかを判断するのに役立ちます。あなたがビットマップのArrayListを保持しているという事実は、問題である可能性が高いことを意味します。 –