由于虚拟内存堆大小有限,我遇到了内存不足的问题 这是我从服务器获取位图的代码:
@SuppressWarnings("unchecked")
public class DrawableManager {
@SuppressWarnings("rawtypes")
private final Map drawableMap;
@SuppressWarnings("rawtypes")
private DrawableManager() {
drawableMap = new HashMap();
}
static private DrawableManager _instance;
static public DrawableManager getInstance() {
if(_instance == null) {
_instance = new DrawableManager();
}
return _instance;
}
public Bitmap fetchBitmap(final String sURL) {
if(sURL.length() == 0)
return null;
Bitmap bm = (Bitmap) drawableMap.get(sURL);
if(bm != null) {
return bm;
}
byte[] imageData = ThumbImg(sURL);
if(imageData == null)
return null;
if(imageData.length > 0) {
bm = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
if(bm != null) {
drawableMap.put(sURL, bm);
}
return bm;
}
else {
return null;
}
}
public void fetchBitmapOnThread(final String sURL, final ImageView imageView) {
if (drawableMap.containsKey(sURL)) {
imageView.setImageBitmap((Bitmap) drawableMap.get(sURL));
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
imageView.setImageBitmap((Bitmap) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
Bitmap bitmap = fetchBitmap(sURL);
Message message = handler.obtainMessage(1, bitmap);
handler.sendMessage(message);
}
};
thread.start();
}
@SuppressWarnings("unused")
public static byte[] ThumbImg(String imgUrl)
{
//first check in the cache, if not available then store in the sd card memory
HttpURLConnection connection = null;
String userAgent = null;
try
{
URL url = new URL(imgUrl);
connection = ( HttpURLConnection ) url.openConnection();
if(userAgent != null) {
connection.setRequestProperty("User-Agent", userAgent);
}
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
int CHUNKSIZE = 8192; //size of fixed chunks
int BUFFERSIZE = 1024; //size of reading buffer
int bytesRead = 0;
byte[] buffer = new byte[BUFFERSIZE]; //initialize buffer
byte[] fixedChunk = new byte[CHUNKSIZE]; //initialize 1st chunk
ArrayList<byte[]> BufferChunkList = new ArrayList<byte[]>(); // List of chunk data
int spaceLeft = CHUNKSIZE;
int chunkIndex = 0;
DataInputStream in = new DataInputStream(connection.getInputStream() );
while( ( bytesRead = in.read( buffer ) ) != -1 ) { //loop until the DataInputStream is completed
if(bytesRead > spaceLeft) {
//copy to end of current chunk
System.arraycopy(buffer, 0, fixedChunk, chunkIndex, spaceLeft);
BufferChunkList.add(fixedChunk);
//create a new chunk, and fill in the leftover
fixedChunk = new byte[CHUNKSIZE];
chunkIndex = bytesRead - spaceLeft;
System.arraycopy(buffer, spaceLeft, fixedChunk, 0, chunkIndex);
} else {
//plenty of space, just copy it in
System.arraycopy(buffer, 0, fixedChunk, chunkIndex, bytesRead);
chunkIndex = chunkIndex + bytesRead;
}
spaceLeft = CHUNKSIZE - chunkIndex;
}
if (in != null) {
in.close();
}
// copy it all into one big array
int responseSize = (BufferChunkList.size() * CHUNKSIZE) + chunkIndex;
Log.d("response size",""+responseSize);
byte[] responseBody = new byte[responseSize];
int index = 0;
for(byte[] b : BufferChunkList) {
System.arraycopy(b, 0, responseBody, index, CHUNKSIZE);
index = index + CHUNKSIZE;
}
System.arraycopy(fixedChunk, 0, responseBody, index, chunkIndex);
return responseBody;
}catch(SocketTimeoutException se)
{
}
catch(Exception e)
{
e.printStackTrace();
}finally
{
if(connection!=null)
connection.disconnect();
}
return null;
}
}
这是我正在使用的代码,这适用于较小的图像,但不适用于大图像。有什么问题需要解决?
由于
答案 0 :(得分:5)
将位图存储在内存中并不总是一个好主意。如果您确实想这样做,请尝试使用SoftReference作为地图。 Check this
将地图的值参数设为SoftReference<Bitmap>
。然后在地图中搜索时使用此代码段
@SuppressWarnings("unchecked")
public class DrawableManager {
@SuppressWarnings("rawtypes")
private final Map<String, SoftReference<Bitmap>> drawableMap;
@SuppressWarnings("rawtypes")
private DrawableManager() {
drawableMap = new HashMap<String, SoftReference<Bitmap>>();
}
static private DrawableManager _instance;
static public DrawableManager getInstance() {
if(_instance == null) {
_instance = new DrawableManager();
}
return _instance;
}
public Bitmap fetchBitmap(final String sURL) {
if(sURL.length() == 0)
return null;
Bitmap bm = null;
SoftReference<Bitmap> reference = drawbaleM.get(imagePath);
if(reference != null) bm = reference.get();
if(bm != null) {
return bm;
}
byte[] imageData = ThumbImg(sURL);
if(imageData == null)
return null;
if(imageData.length > 0) {
bm = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
if(bm != null) {
drawableMap.put(sURL, bm);
}
return bm;
}
else {
return null;
}
}
public void fetchBitmapOnThread(final String sURL, final ImageView imageView) {
if (drawableMap.containsKey(sURL)) {
imageView.setImageBitmap((Bitmap) drawableMap.get(sURL));
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
imageView.setImageBitmap((Bitmap) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
Bitmap bitmap = fetchBitmap(sURL);
Message message = handler.obtainMessage(1, bitmap);
handler.sendMessage(message);
}
};
thread.start();
}
@SuppressWarnings("unused")
public static byte[] ThumbImg(String imgUrl)
{
//first check in the cache, if not available then store in the sd card memory
HttpURLConnection connection = null;
String userAgent = null;
try
{
URL url = new URL(imgUrl);
connection = ( HttpURLConnection ) url.openConnection();
if(userAgent != null) {
connection.setRequestProperty("User-Agent", userAgent);
}
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
int CHUNKSIZE = 8192; //size of fixed chunks
int BUFFERSIZE = 1024; //size of reading buffer
int bytesRead = 0;
byte[] buffer = new byte[BUFFERSIZE]; //initialize buffer
byte[] fixedChunk = new byte[CHUNKSIZE]; //initialize 1st chunk
ArrayList<byte[]> BufferChunkList = new ArrayList<byte[]>(); // List of chunk data
int spaceLeft = CHUNKSIZE;
int chunkIndex = 0;
DataInputStream in = new DataInputStream(connection.getInputStream() );
while( ( bytesRead = in.read( buffer ) ) != -1 ) { //loop until the DataInputStream is completed
if(bytesRead > spaceLeft) {
//copy to end of current chunk
System.arraycopy(buffer, 0, fixedChunk, chunkIndex, spaceLeft);
BufferChunkList.add(fixedChunk);
//create a new chunk, and fill in the leftover
fixedChunk = new byte[CHUNKSIZE];
chunkIndex = bytesRead - spaceLeft;
System.arraycopy(buffer, spaceLeft, fixedChunk, 0, chunkIndex);
} else {
//plenty of space, just copy it in
System.arraycopy(buffer, 0, fixedChunk, chunkIndex, bytesRead);
chunkIndex = chunkIndex + bytesRead;
}
spaceLeft = CHUNKSIZE - chunkIndex;
}
if (in != null) {
in.close();
}
// copy it all into one big array
int responseSize = (BufferChunkList.size() * CHUNKSIZE) + chunkIndex;
Log.d("response size",""+responseSize);
byte[] responseBody = new byte[responseSize];
int index = 0;
for(byte[] b : BufferChunkList) {
System.arraycopy(b, 0, responseBody, index, CHUNKSIZE);
index = index + CHUNKSIZE;
}
System.arraycopy(fixedChunk, 0, responseBody, index, chunkIndex);
return responseBody;
}catch(SocketTimeoutException se)
{
}
catch(Exception e)
{
e.printStackTrace();
}finally
{
if(connection!=null)
connection.disconnect();
}
return null;
}
}
请注意,这并不能保证从OOM中解脱出来。显示大位图并不总是一个好主意。
您可以使用的另一个选项是使用BitmapFactory.Options inSampleSize参数
答案 1 :(得分:0)
BitmapFactory.decodeByteArray()在Native堆中创建位图数据,而不是VM堆。有关详细信息,请参阅BitmapFactory OOM driving me nuts。
您可以监控本机堆(根据BitmapFactory OOM driving me nuts),如果您的空间不足,则可以下采样。</ p>