android显示图片内存溢出问题最近在做一个应用,要循环显示图片,可是图片很大,每个5M左右,如果按图片原来大
android显示图片内存溢出问题
最近在做一个应用,要循环显示图片,可是图片很大,每个5M左右,如果按图片原来大小显示,在显示两个图片之后必会内存溢出,谁能给个图片压缩显示方法,谢谢!!!
[解决办法]
........5M
这个就算recycle也没用了...
我觉得你可以这样,创建一张全局的bitmap(当然要按最大的创建),然后每个图片读取都按照字节的方式读出来,之后set个体这个全局的bitmap,显示的时候就显示这个全局的,一个用完就清空一下,在读取另一张,这样保证只有一个bitmap在占用内存....
[解决办法]
我有图片压缩的一个类你看看哈:
- Java code
import com.xmobileapp.pictureviewer.R;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BlurMaskFilter;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.os.Handler;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.View;import android.view.Window;import android.view.GestureDetector.SimpleOnGestureListener;import android.widget.Scroller;public class PictureShow extends Activity { private PictureShowUtils mAllImages = new PictureShowUtils(); boolean mLayoutComplete; boolean mPausing = false; PictureSlideView mPictureSlideView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.main); mPictureSlideView = (PictureSlideView) findViewById(R.id.grid); mPictureSlideView.requestFocus(); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return super.onKeyUp(keyCode, event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { int sel = mPictureSlideView.mSelImageIndex; int count = mAllImages.getCount(); switch (keyCode) { case KeyEvent.KEYCODE_DPAD_UP: if (sel >= 1) { sel--; mPictureSlideView.ScrollUp(); } break; case KeyEvent.KEYCODE_DPAD_DOWN: if (sel < count - 1) { sel++; mPictureSlideView.scrollDown(); } break; default: break; } mPictureSlideView.mSelImageIndex = sel; mPictureSlideView.mImageBlockManager.loadSelBlock(sel); mPictureSlideView.invalidate(); return super.onKeyDown(keyCode, event); } @Override public void onPause() { super.onPause(); mPausing = true; } @Override public void onResume() { super.onResume(); mPausing = false; } public static class PictureSlideView extends View { // 布局信息 class LayoutSpec { LayoutSpec(int cols, int w, int h, int leftEdgePadding, int rightEdgePadding, int intercellSpacing) { mColumns = cols; mCellWidth = w; mCellHeight = h; mLeftEdgePadding = leftEdgePadding; mRightEdgePadding = rightEdgePadding; mCellSpacing = intercellSpacing; } int mColumns; int mCellWidth, mCellHeight; int mLeftEdgePadding, mRightEdgePadding; int mCellSpacing; }; private class ImageBlockManager { private int mBlockCacheFirstBlockNumber = 0; private int mBlockCacheStartOffset = 0; //缩略图缓存 private ImageBlock[] mBlockCache; //选定的缩略图对象 private ImageBlock mSelBlock; //一屏上缩略图的行数 private static final int sRowsPerPage = 4; //缩略图缓存大小参数 private static final int sPagesPreCache = 2; private static final int sPagesPostCache = 2; // 放大预览图的尺寸 private static final int sSelBlockWidth = 200; private static final int sSelBlockHeight = 200; private Bitmap mMissingImageThumbnailBitmap; ImageBlockManager(Context context) { mContext = context; mBlockCache = new ImageBlock[sRowsPerPage * (sPagesPreCache + sPagesPostCache + 1)]; for (int i = 0; i < mBlockCache.length; i++) { mBlockCache[i] = new ImageBlock(); } /* 读取图片 */ loadBlocks(); mSelBlock = new ImageBlock(sSelBlockWidth, sSelBlockHeight); } int blockHeight() { return mCurrentSpec.mCellSpacing + mCurrentSpec.mCellHeight + mCurrentSpec.mCellSpacing; } int blockWidth() { return mCurrentSpec.mCellSpacing + mCurrentSpec.mCellWidth + mCurrentSpec.mCellSpacing; } void loadSelBlock(int pos) { mSelBlock.loadSelImage(pos); } private void paintSelBlock(Canvas canvas) { int pos = mSelImageIndex; if (pos < 0) return; Bitmap b = mSelBlock.mBitmap; if (b == null) { return; } int xPos = 0; int yPos = 0; yPos = mScrollY + mCurrentSpec.mCellSpacing; xPos = mCurrentSpec.mCellWidth + mCurrentSpec.mLeftEdgePadding; canvas.drawBitmap(b, xPos, yPos, mGridViewPaint); } // 获取代表“没有缩略图”的图片对象 public Bitmap getErrorBitmap() { mMissingImageThumbnailBitmap = BitmapFactory.decodeResource( PictureSlideView.this.getResources(), R.drawable.nothumbnail); return mMissingImageThumbnailBitmap; }
[解决办法]
接上
- Java code
private void loadBlocks() { ImageBlock[] blocks = mBlockCache; int numBlocks = blocks.length; int first = 0; for (int i = 0; i < numBlocks; i++) { int j = first + i; if (j >= numBlocks) j -= numBlocks; ImageBlock b = blocks[j]; b.mBlockNumber = j; if (b.loadBlock() == 0) break; } } void doDraw(Canvas canvas) { ImageBlockManager.ImageBlock[] blocks = mBlockCache; if (blocks[0] == null) { return; } final int thisHeight = getHeight(); final int height = blocks[0].mBitmap.getHeight(); final int scrollPos = mScrollY; int currentBlock = (scrollPos < 0) ? ((scrollPos - height + 1) / height) : (scrollPos / height); while (true) { final int yPos = currentBlock * height; if (yPos >= scrollPos + thisHeight) { break; } int effectiveOffset = (mBlockCacheStartOffset + (currentBlock++ - mBlockCacheFirstBlockNumber)) % blocks.length; ImageBlock block = blocks[effectiveOffset]; if (block == null) break; Bitmap b = block.mBitmap; if (b == null) { break; } canvas.drawBitmap(b, 0, yPos, mGridViewPaint); } // end of while /* Paint Selection */ paintSelBlock(canvas); }/* end of doDraw */ private class ImageBlock { private static final int mBlurRadius = 5; private static final int mBlockAlpha = 180; private static final int mBorderAlpha = 180; private static final int mSelBorderAlpha = 150; Drawable mCellOutline; Bitmap mBitmap; Canvas mCanvas; Paint mPaint = new Paint(); int mBlockNumber; boolean mIsVisible; ImageBlock() { mBitmap = Bitmap.createBitmap(getWidth(), blockHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mPaint.setTextSize(14F); mPaint.setStyle(Paint.Style.FILL); mPaint.setAlpha(mBlockAlpha); mBlockNumber = -1; mCellOutline = PictureSlideView.this.getResources() .getDrawable(android.R.drawable.gallery_thumb); mCellOutline.setAlpha(mBorderAlpha); } ImageBlock(int w, int h) { mBitmap = Bitmap .createBitmap(w, h, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mPaint.setTextSize(14F); mPaint.setStyle(Paint.Style.FILL); mPaint.setFilterBitmap(true); mPaint.setMaskFilter(new BlurMaskFilter(mBlurRadius, BlurMaskFilter.Blur.NORMAL)); mBlockNumber = -1; mCellOutline = PictureSlideView.this.getResources() .getDrawable(android.R.drawable.gallery_thumb); mCellOutline.setAlpha(mSelBorderAlpha); } private int loadBlock() { int count = mGallery.mAllImages.getCount(); int base = (mBlockNumber * mCurrentSpec.mColumns); for (int col = 0; col < mCurrentSpec.mColumns; col++) { int spacing = mCurrentSpec.mCellSpacing; int leftSpacing = mCurrentSpec.mLeftEdgePadding; final int yPos = spacing; final int xPos = leftSpacing + (col * (mCurrentSpec.mCellWidth + spacing)); int pos = base + col; if (pos >= count) break; Bitmap b = mGallery.mAllImages.getImageAt(pos); if (b == null) { return 0; } drawBlockBitmap(b, xPos, yPos, mCurrentSpec.mCellWidth, mCurrentSpec.mCellHeight); } return 1; } private int loadSelImage(int pos) { final int yPos = 0; final int xPos = 0; Bitmap b = mGallery.mAllImages.getImageAt(pos); drawSelBlockBitmap(b, xPos, yPos, sSelBlockWidth, sSelBlockHeight); return 1; } private void drawBlockBitmap(Bitmap b, int left, int top, int width, int height) { mCanvas.setBitmap(mBitmap); if (b != null) { //根据图片的大小进行裁剪或缩放,形状均为正方形。 int w = width; int h = height; int bw = b.getWidth(); int bh = b.getHeight(); int deltaW = bw - w; int deltaH = bh - h; if (deltaW < 10 && deltaH < 10) { int halfDeltaW = deltaW / 2; int halfDeltaH = deltaH / 2; android.graphics.Rect src = new android.graphics.Rect( 0 + halfDeltaW, 0 + halfDeltaH, bw - halfDeltaW, bh - halfDeltaH); android.graphics.Rect dst = new android.graphics.Rect( left, top, left + w, top + h); mCanvas.drawBitmap(b, src, dst, mPaint); } else { int l = (bw - w) / 2; int t = (bh - h) / 2; android.graphics.Rect src = new android.graphics.Rect( l, t, l + w, t + h); android.graphics.Rect dst = new android.graphics.Rect( left, top, left + w, top + h); mCanvas.drawBitmap(b, src, dst, mPaint); } } else { //如果缩略图不能获得,则使用默认的错误图片代替 Bitmap error = mImageBlockManager.getErrorBitmap(); int w = error.getWidth(); int h = error.getHeight(); Rect source = new Rect(0, 0, w, h); int l = (w - w) / 2 + left; int t = (h - h) / 2 + top; Rect dest = new Rect(l, t, l + w, t + h); mCanvas.drawBitmap(error, source, dest, mPaint); } int[] stateSet = EMPTY_STATE_SET; paintBorder(stateSet, left, top, left + width, top + height); }
[解决办法]
recycle并不能及时回收图片,只是告诉虚拟机我需要回收该图片资源,Java中没有手工回收资源的方法。。
1、修改android底层的内存限制。。。放开内存
2、用楼上的做法进行缩放, opts.inSampleSize = 2;表明缩放为原图的长宽各一半。。。用弱引用引用图片,保证及时的回收。。
[解决办法]
执行了bitmap.recycle()后,直接让bitmap对象赋予null,这样可以立即释放的。不过要说的是android处理大图片很愁人的,ram太小了,没办法,vm限制也大,哈哈
