De mémoire exception à cause de la grande taille du bitmap
J'ai un problème de mémoire insuffisante en raison de la limitation de la mémoire virtuelle de la taille du segment.
Voici mon code pour l'extraction de bitmap à partir du serveur:
@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;
}
}
C'est le code que j'utilise, cela fonctionne très bien avec des images plus petites, mais pas pour les images de grande taille. Quel est le problème et à le résoudre?
Grâce
OriginalL'auteur Nikki | 2011-03-16
Vous devez vous connecter pour publier un commentaire.
N'est pas toujours une bonne idée de stocker des images dans la mémoire. Si vous voulez vraiment le faire, puis essayez d'utiliser SoftReference pour votre carte. Cochez cette
rendre votre carte de valeur de l'argument que
SoftReference<Bitmap>
. Puis en cherchant dans la carte, utiliser ce bout de codeVeuillez noter que ce n'est pas la garantie d'allégement de OOM. Il n'est pas toujours une bonne idée d'afficher de grandes images.
Une autre option que vous pouvez aller après utilisation BitmapFactory.Options inSampleSize argument
exemple de code donné ci-dessus
Pouvez-vous s'il vous plaît modifier votre code d'exemple dans la mine de code car c'est en donnant l'erreur de mon côté, tout en faisant des changements selon votre exemple de code
code modifié pour utiliser votre extrait de code
Mais il montre des erreurs dans drawbleM.get() ne pourra pas lancer dans sofwarereferense
OriginalL'auteur pankajagarwal
BitmapFactory.decodeByteArray() crée les données de l'image dans le tas Natif, pas la VM tas. Voir BitmapFactory OOM me rend fou pour plus de détails.
Vous pouvez surveiller le tas Natif (comme par BitmapFactory OOM me rend fou) et de sous-échantillonner si vous êtes à court d'espace.
Basé sur la réponse liée, depuis le Nid d'abeille Bitmap allouée à la machine virtuelle tas. Ce n'est donc pas une solution plus si votre minSDK de plus de 13
OriginalL'auteur Torid