我的应用中有20张图片。所有图像均为640 * 360分辨率,每个图像不超过60KB。
我利用Viewpager来滑动图像。并在ViewPager中使用ViewFlipper来翻转图像。当用户点击它时,我会显示图像的相应文本。
问题是当我来回滑动5次时,我得到OutOfMemory异常。我读了各种Stackoverflow线程here!,here!,here!和Handling Large Bitmaps Efficiently!但无法解决问题,
这是代码,
在Main_Fragment.java中,
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
--- some code ---
--- some more code ---
View v = inflater.inflate(R.layout.main_fragment, container,false);
viewAnimator = ((ViewAnimator) v.findViewById(R.id.cardFlipper));
TextView caption_text = (TextView) v.findViewById(R.id.caption_text);
caption_text.setText(caption.toUpperCase());
ImageView main_img = (ImageView) v.findViewById(R.id.main_img);
int mainimg_resID = getResources().getIdentifier(mainimg,"drawable",context.getPackageName());
Bitmap icon = decodeSampledBitmapFromResource(getResources(),mainimg_resID,640,360);
main_img.setImageBitmap(icon);
viewAnimator.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AnimationFactory.flipTransition((ViewAnimator) v,FlipDirection.LEFT_RIGHT);
}
});
return v;
}
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;
}
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);
}
你能告诉我我做错了吗?这让我疯狂了过去几天:(
答案 0 :(得分:0)
Bitmap icon = decodeSampledBitmapFromResource(getResources(),mainimg_resID,640,360);
你弄错了:reqHeight
和reqWidth
参数应该是图像视图的宽度和高度,而不是原始图像尺寸!!这就是calculateInSampleSize()
的全部内容..
所以,您应该执行以下操作:
Bitmap icon = decodeSampledBitmapFromResource(getResources(),mainimg_resID,main_img.getWidth(), main_img.getHeight());
通过解码基于仅显示所需尺寸计算的比例的位图 - 结果位图分配将是最小的。
顺便说一下 - 您使用的资源大小只有60KB的事实不会改变任何东西。实际上 - 图像内存大小(Kilobites / Megas)对分配的位图没有任何影响。这只是解决方案的唯一因素!
修改强>
因为imageView维度在onCreateView()
方法中仍然为零 - 你只有在得到它后才能进行解码:
--- some code ---
--- some more code ---
View v = inflater.inflate(R.layout.main_fragment, container,false);
viewAnimator = ((ViewAnimator) v.findViewById(R.id.cardFlipper));
TextView caption_text = (TextView) v.findViewById(R.id.caption_text);
caption_text.setText(caption.toUpperCase());
final ImageView main_img = (ImageView) v.findViewById(R.id.main_img);
ViewTreeObserver vto = main_img.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final ViewTreeObserver obs = main_img.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
// do here the image decoding + setting the image to the image view
Bitmap icon = decodeSampledBitmapFromResource(getResources(),mainimg_resID,main_img.getWidth(), main_img.getHeight());
// setImage....
}
});
viewAnimator.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AnimationFactory.flipTransition((ViewAnimator) v,FlipDirection.LEFT_RIGHT);
}
});
return v;
编辑2
永远不要将wrap_content
用于ImageView
。那是因为它强制视图的大小与原始图像(可能非常大)相反,而不是相反。在计算所需的比例时 - 整点是在ImageView
维度与原始图像(资源/文件/流)维度之间进行比较。这就是为什么它没有任何意义使用wrap_content
。