Eu tenho uma exibição de lista com alguns botões de imagem em cada linha. Quando você clica na linha da lista, ela lança uma nova atividade. Eu tive que criar minhas próprias guias por causa de um problema com o layout da câmera. A atividade iniciada para o resultado é um mapa. Se eu clicar no meu botão para iniciar a visualização da imagem (carregar uma imagem do cartão SD), o aplicativo retornará da atividade de volta à listview
atividade para o manipulador de resultados para reiniciar minha nova atividade, que nada mais é do que um widget de imagem.
A visualização da imagem na exibição de lista está sendo feita com o cursor e ListAdapter
. Isso torna bastante simples, mas não tenho certeza de como posso colocar uma imagem redimensionada (ou seja, tamanho de bit menor e não pixel como o src
botão de imagem em tempo real. Acabei de redimensionar a imagem que saiu da câmera do telefone.
O problema é que recebo um erro de falta de memória quando ele tenta voltar e reiniciar a 2ª atividade.
- Existe uma maneira de criar o adaptador de lista facilmente linha por linha, onde eu possa redimensionar rapidamente (um pouco )?
Isso seria preferível, pois também preciso fazer algumas alterações nas propriedades dos widgets / elementos em cada linha, pois não consigo selecionar uma linha com a tela de toque por causa do problema de foco. ( Eu posso usar bola de rolo. )
- Eu sei que posso redimensionar fora da banda e salvar a minha imagem, mas não é exatamente isso que eu quero fazer, mas algum código de exemplo para isso seria bom.
Assim que desabilitei a imagem na exibição de lista, ela funcionou bem novamente.
FYI: Era assim que eu fazia:
String[] from = new String[] { DBHelper.KEY_BUSINESSNAME,DBHelper.KEY_ADDRESS,DBHelper.KEY_CITY,DBHelper.KEY_GPSLONG,DBHelper.KEY_GPSLAT,DBHelper.KEY_IMAGEFILENAME + ""};
int[] to = new int[] {R.id.businessname,R.id.address,R.id.city,R.id.gpslong,R.id.gpslat,R.id.imagefilename };
notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);
Onde R.id.imagefilename
está um ButtonImage
.
Aqui está o meu LogCat:
01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.
01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes
01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ImageView.resolveUri(ImageView.java:484)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ImageView.setImageURI(ImageView.java:281)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.CursorAdapter.getView(CursorAdapter.java:150)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.AbsListView.obtainView(AbsListView.java:1057)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.makeAndAddView(ListView.java:1616)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.fillSpecific(ListView.java:1177)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.layoutChildren(ListView.java:1454)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.AbsListView.onLayout(AbsListView.java:937)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.onLayout(LinearLayout.java:922)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.onLayout(LinearLayout.java:920)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.ViewRoot.performTraversals(ViewRoot.java:771)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.os.Handler.dispatchMessage(Handler.java:88)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.os.Looper.loop(Looper.java:123)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.app.ActivityThread.main(ActivityThread.java:3742)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at java.lang.reflect.Method.invokeNative(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at java.lang.reflect.Method.invoke(Method.java:515)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at dalvik.system.NativeStart.main(Native Method)
01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed
Também tenho um novo erro ao exibir uma imagem:
01-25 22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d
01-25 22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri:
01-25 22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.
01-25 22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes
01-25 22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed
fonte
Respostas:
A classe de treinamento do Android , " Exibindo bitmaps com eficiência ", oferece ótimas informações para entender e lidar com a exceção
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
ao carregar bitmaps.Leia dimensões e tipo de bitmap
A
BitmapFactory
classe fornece vários métodos de descodificação (decodeByteArray()
,decodeFile()
,decodeResource()
, etc.) para a criação de umaBitmap
de várias fontes. Escolha o método de decodificação mais apropriado com base na fonte de dados da imagem. Esses métodos tentam alocar memória para o bitmap construído e, portanto, podem facilmente resultar em umaOutOfMemory
exceção. Cada tipo de método de decodificação possui assinaturas adicionais que permitem especificar opções de decodificação por meio daBitmapFactory.Options
classe. Definir ainJustDecodeBounds
propriedade comotrue
decodificação evita a alocação de memória, retornandonull
para o objeto bitmap, mas definindooutWidth
,outHeight
eoutMimeType
. Essa técnica permite que você leia as dimensões e o tipo dos dados da imagem antes da construção (e alocação de memória) do bitmap.Para evitar
java.lang.OutOfMemory
exceções, verifique as dimensões de um bitmap antes de decodificá-lo, a menos que você confie totalmente na fonte para fornecer dados de imagem de tamanho previsível que cabem confortavelmente na memória disponível.Carregar uma versão reduzida na memória
Agora que as dimensões da imagem são conhecidas, elas podem ser usadas para decidir se a imagem completa deve ser carregada na memória ou se uma versão com subamostra deve ser carregada. Aqui estão alguns fatores a serem considerados:
Por exemplo, não vale a pena carregar uma imagem de 1024x768 pixels na memória se ela for exibida em uma miniatura de 128x96 pixels em uma
ImageView
.Para dizer a decodificador para subamostra a imagem, carregar uma versão menor na memória, conjunto
inSampleSize
paratrue
em seuBitmapFactory.Options
objeto. Por exemplo, uma imagem com resolução 2048x1536 decodificada com uminSampleSize
de 4 produz um bitmap de aproximadamente 512x384. Carregar isso na memória usa 0,75 MB em vez de 12MB para a imagem completa (assumindo uma configuração de bitmap deARGB_8888
). Aqui está um método para calcular um valor de tamanho de amostra que é uma potência de dois com base na largura e altura do destino:Para usar esse método, decodifique primeiro com
inJustDecodeBounds
settrue
, passe as opções e decodifique novamente usando o novoinSampleSize
valor einJustDecodeBounds
configure parafalse
:Esse método facilita o carregamento de um bitmap de tamanho arbitrariamente grande em um
ImageView
que exibe uma miniatura de 100 x 100 pixels, conforme mostrado no código de exemplo a seguir:Você pode seguir um processo semelhante para decodificar bitmaps de outras fontes, substituindo o
BitmapFactory.decode*
método apropriado conforme necessário.fonte
Para corrigir o erro OutOfMemory, você deve fazer algo assim:
Esta
inSampleSize
opção reduz o consumo de memória.Aqui está um método completo. Primeiro, ele lê o tamanho da imagem sem decodificar o conteúdo. Então ele encontra o melhor
inSampleSize
valor, deve ter uma potência de 2 e, finalmente, a imagem é decodificada.fonte
Fiz uma pequena melhoria no código do Fedor. Basicamente, faz o mesmo, mas sem o (na minha opinião) feio while loop e sempre resulta em uma potência de dois. Parabéns ao Fedor por fazer a solução original, fiquei preso até encontrar a dele e depois consegui fazer essa :)
fonte
BitmapFactory.decodeStream()
. Você não precisa salvar uma referência para cada um deles para que eles possam ser fechados em umfinally
bloco?Sou da experiência do iOS e fiquei frustrado ao descobrir um problema com algo tão básico quanto carregar e mostrar uma imagem. Afinal, todo mundo que está tendo esse problema está tentando exibir imagens de tamanho razoável. Enfim, aqui estão as duas alterações que corrigiram meu problema (e tornaram meu aplicativo muito responsivo).
1) Toda vez que fizer isso
BitmapFactory.decodeXYZ()
, passe um aBitmapFactory.Options
cominPurgeable
definido comotrue
(e de preferência cominInputShareable
também definido comotrue
).2) NUNCA use
Bitmap.createBitmap(width, height, Config.ARGB_8888)
. Quero dizer NUNCA! Eu nunca tive essa coisa não aumentar o erro de memória depois de algumas passagens. Nenhuma quantidade derecycle()
,System.gc()
, qualquer que seja ajudado. Sempre levantava exceção. A outra maneira que realmente funciona é ter uma imagem fictícia em seus drawables (ou outro Bitmap que você decodificou usando a etapa 1 acima), redimensioná-la para o que quiser e manipular o Bitmap resultante (como passá-lo para um Canvas para mais diversão). Então, o que você deve usar em vez disso é:Bitmap.createScaledBitmap(srcBitmap, width, height, false)
. Se, por qualquer motivo, você DEVE usar o método de criação de força bruta, passe pelo menosConfig.ARGB_4444
.É quase garantido que você economize horas, se não dias. Tudo o que fala sobre dimensionar a imagem, etc., realmente não funciona (a menos que você considere obter um tamanho errado ou degradar a imagem como uma solução).
fonte
BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true;
eBitmap.createScaledBitmap(srcBitmap, width, height, false);
resolvi meu problema com exceção de falta de memória no android 4.0.0. Obrigado companheiro!BitmapFactory.Options.inPurgeable
eBitmapFactory.Options.inInputShareable
estão obsoletos developer.android.com/reference/android/graphics/…É um bug conhecido , não é por causa de arquivos grandes. Como o Android armazena em cache os Drawables, fica sem memória depois de usar poucas imagens. Mas eu encontrei uma maneira alternativa para isso, ignorando o sistema de cache padrão do Android.
Solução : Mova as imagens para a pasta "assets" e use a seguinte função para obter o BitmapDrawable:
fonte
Eu tive esse mesmo problema e o resolvi evitando as funções BitmapFactory.decodeStream ou decodeFile e, em vez disso, usei
BitmapFactory.decodeFileDescriptor
decodeFileDescriptor
parece que chama métodos nativos diferentes do decodeStream / decodeFile.De qualquer forma, o que funcionou foi isso (observe que eu adicionei algumas opções como algumas acima, mas não foi isso que fez a diferença. O mais importante é a chamada para BitmapFactory.decodeFileDescriptor em vez de decodeStream ou decodeFile ):
Eu acho que há um problema com a função nativa usada em decodeStream / decodeFile. Confirmei que um método nativo diferente é chamado ao usar decodeFileDescriptor. Também o que eu li é "que as Imagens (Bitmaps) não são alocadas de maneira Java padrão, mas por meio de chamadas nativas; as alocações são feitas fora do heap virtual, mas são contadas contra ele! "
fonte
Eu acho que a melhor maneira de evitar o
OutOfMemoryError
é enfrentá-lo e entendê-lo.Eu fiz um aplicativo para causar intencionalmente
OutOfMemoryError
e monitorar o uso de memória.Depois de fazer muitas experiências com este aplicativo, tenho as seguintes conclusões:
Vou falar sobre as versões do SDK antes da Honey Comb primeiro.
O bitmap é armazenado no heap nativo, mas será coletado o lixo automaticamente, sendo desnecessário chamar recycle ().
Se {tamanho da pilha da VM} + {memória de pilha nativa alocada}> = = {limite de tamanho da pilha da VM para o dispositivo} e você estiver tentando criar bitmap, o OOM será lançado.
AVISO: O TAMANHO HEAP DA VM é contado em vez da MEMÓRIA ALOCADA DA VM.
O tamanho da pilha da VM nunca diminui após o crescimento, mesmo que a memória da VM alocada seja reduzida.
Portanto, você deve manter o pico da memória da VM o mais baixo possível para impedir que o tamanho da pilha da VM cresça muito demais para economizar memória disponível para os bitmaps.
Chamar manualmente System.gc () não faz sentido, o sistema o chamará primeiro antes de tentar aumentar o tamanho do heap.
O tamanho nativo da pilha nunca diminuirá também, mas não é contabilizado para o OOM, portanto, não é necessário se preocupar com isso.
Então, vamos falar sobre o SDK Starts do Honey Comb.
O bitmap é armazenado no heap da VM, a memória nativa não é contada para o OOM.
A condição para o OOM é muito mais simples: {tamanho da pilha da VM}> = = {limite de tamanho da pilha da VM para o dispositivo}.
Para que você tenha mais memória disponível para criar bitmap com o mesmo limite de tamanho de heap, é menos provável que o OOM seja lançado.
Aqui estão algumas das minhas observações sobre coleta de lixo e vazamento de memória.
Você pode vê-lo no aplicativo. Se uma Atividade executou um AsyncTask que ainda estava em execução após a Atividade ter sido destruída, a Atividade não será coletada como lixo até que o AsyncTask seja concluído.
Isso ocorre porque o AsyncTask é uma instância de uma classe interna anônima e contém uma referência da atividade.
Chamar AsyncTask.cancel (true) não interromperá a execução se a tarefa estiver bloqueada em uma operação de E / S no encadeamento em segundo plano.
Os retornos de chamada também são classes internas anônimas; portanto, se uma instância estática do seu projeto os mantiver e não os liberar, a memória vazará.
Se você agendou uma tarefa repetida ou atrasada, por exemplo, um Timer e não chamou cancel () e purge () em onPause (), a memória vazaria.
fonte
private static class
na mesma classe. Eles não vão ter qualquer referência à actividade (a menos que você lhes dá um claro)Ultimamente, tenho visto muitas perguntas sobre exceções de OOM e cache. O guia do desenvolvedor tem um artigo realmente bom sobre isso, mas alguns tendem a falhar ao implementá-lo de maneira adequada.
Por isso, escrevi um exemplo de aplicativo que demonstra o cache em um ambiente Android. Esta implementação ainda não obteve um OOM.
Veja no final desta resposta um link para o código-fonte.
Requisitos:
Recursos:
ListView
distância, ele simplesmente não vai baixar os bitmaps entreIsso não inclui:
Código de amostra:
As imagens que estão sendo baixadas são imagens (75x75) do Flickr. No entanto, coloque os URLs da imagem que você deseja processar e o aplicativo a reduzirá se exceder o máximo. Nesta aplicação, os URLs estão simplesmente em uma
String
matriz.O
LruCache
tem uma boa maneira de lidar com bitmaps. No entanto, nesta aplicação, coloquei uma instância de umaLruCache
outra classe de cache que criei para tornar o aplicativo mais viável.Coisas críticas do Cache.java (o
loadBitmap()
método é o mais importante):Você não precisa editar nada no arquivo Cache.java, a menos que queira implementar o cache de disco.
Material crítico de MainActivity.java:
getView()
é chamado com muita frequência. Normalmente, não é uma boa ideia fazer o download de imagens lá se não tivermos implementado uma verificação que garanta que não iniciaremos uma quantidade infinita de threads por linha. O Cache.java verifica se orowObject.mBitmapUrl
já está em uma tarefa e, se estiver, não iniciará outra. Portanto, provavelmente não estamos excedendo a restrição da fila de trabalho doAsyncTask
pool.Baixar:
Você pode fazer o download do código-fonte em https://www.dropbox.com/s/pvr9zyl811tfeem/ListViewImageCache.zip .
Últimas palavras:
Eu testei isso por algumas semanas agora, ainda não recebi uma única exceção do OOM. Eu testei isso no emulador, no meu Nexus One e no meu Nexus S. Testei URLs de imagem que contêm imagens com qualidade HD. O único gargalo é que leva mais tempo para fazer o download.
Há apenas um cenário possível em que posso imaginar que o OOM aparecerá, ou seja, se fizermos o download de muitas imagens realmente grandes e, antes que elas sejam dimensionadas e colocadas no cache, ocupem simultaneamente mais memória e causam um OOM. Mas isso não é nem mesmo uma situação ideal e provavelmente não será possível resolver de uma maneira mais viável.
Relatar erros nos comentários! :-)
fonte
Fiz o seguinte para pegar a imagem e redimensioná-la rapidamente. Espero que isto ajude
fonte
Parece que este é um problema muito demorado, com muitas explicações diferentes. Eu segui o conselho das duas respostas apresentadas mais comuns aqui, mas nenhuma delas resolveu meus problemas da VM alegando que não podia pagar os bytes para executar a parte de decodificação do processo. Depois de algumas escavações, aprendi que o verdadeiro problema aqui é o processo de decodificação que tira o NATIVE heap .
Veja aqui: BitmapFactory OOM me deixando louco
Isso me levou a outro tópico de discussão em que encontrei mais algumas soluções para esse problema. Uma é ligar
System.gc();
manualmente após a exibição da imagem. Mas isso faz com que seu aplicativo use MAIS memória, em um esforço para reduzir a pilha nativa. A melhor solução a partir do lançamento do 2.0 (Donut) é usar a opção BitmapFactory "inPurgeable". Então eu simplesmente adicioneio2.inPurgeable=true;
logo depoiso2.inSampleSize=scale;
.Mais sobre esse tópico aqui: O limite de memória é de apenas 6M?
Agora, tendo dito tudo isso, também sou um idiota completo com Java e Android. Portanto, se você acha que essa é uma maneira terrível de resolver esse problema, provavelmente está certo. ;-) Mas isso fez maravilhas para mim e achei impossível executar a VM fora do cache de heap agora. A única desvantagem que posso encontrar é que você está destruindo sua imagem desenhada em cache. O que significa que, se você voltar DIRETAMENTE àquela imagem, estará redesenhando-a sempre. No caso de como meu aplicativo funciona, isso não é realmente um problema. Sua milhagem pode variar.
fonte
infelizmente, se nenhuma das opções acima funcionar, adicione isso ao seu arquivo de manifesto . Etiqueta interna da aplicação
fonte
Use isto
bitmap.recycle();
Isso ajuda sem nenhum problema de qualidade de imagem.fonte
Eu tenho uma solução muito mais eficaz que não precisa de escala de nenhum tipo. Simplesmente decodifique seu bitmap apenas uma vez e, em seguida, armazene-o em cache em um mapa com seu nome. Em seguida, recupere o bitmap com o nome e defina-o no ImageView. Não há mais nada a ser feito.
Isso funcionará porque os dados binários reais do bitmap decodificado não são armazenados no heap da dalvik VM. É armazenado externamente. Portanto, toda vez que você decodifica um bitmap, ele aloca memória fora do heap da VM, que nunca é recuperada pelo GC
Para ajudá-lo a apreciar melhor isso, imagine que você tenha mantido sua imagem na pasta de desenho. Você acabou de obter a imagem executando getResources (). GetDrwable (R.drawable.). Isso NÃO decodificará sua imagem toda vez, mas reutilizará uma instância já decodificada toda vez que você a chamar. Então, em essência, é armazenado em cache.
Agora, como sua imagem está em um arquivo em algum lugar (ou pode vir de um servidor externo), é SUA responsabilidade armazenar em cache a instância de bitmap decodificada para ser reutilizada em qualquer lugar que seja necessário.
Espero que isto ajude.
fonte
Resolvi o mesmo problema da seguinte maneira.
fonte
Há duas questões aqui....
fonte
Isso funcionou para mim!
fonte
Nenhuma das respostas acima funcionou para mim, mas eu criei uma solução horrivelmente feia que resolveu o problema. Adicionei uma imagem muito pequena, de 1 x 1 pixel ao meu projeto como recurso e carreguei-a no meu ImageView antes de chamar a coleta de lixo. Eu acho que o ImageView não estava lançando o Bitmap, então a GC nunca o pegou. É feio, mas parece estar funcionando por enquanto.
fonte
bitmap
no código acima, a imagem anterior já é exibida, é necessário reciclar, limpar todas as referências a ela, fazer com que aimageView
esqueça também, definindo uma pequena substituiçãogc()
; e depois de tudo isso: carregue sua NOVA imagembitmap
e exiba-a...
no código acima.Ótimas respostas aqui, mas eu queria uma classe totalmente utilizável para resolver esse problema.
Aqui está minha classe BitmapHelper que é a prova OutOfMemoryError :-)
fonte
Isso funciona para mim.
e isso é em C # monodroid. você pode facilmente mudar o caminho da imagem. O importante aqui são as opções a serem definidas.
fonte
Este parece ser o local apropriado para compartilhar minha classe de utilitário para carregar e processar imagens com a comunidade; você pode usá-lo e modificá-lo livremente.
fonte
Em um dos meus aplicativos, preciso tirar uma foto
Camera/Gallery
. Se o usuário clicar na imagem da câmera (pode ser 2MP, 5MP ou 8MP), o tamanho da imagem varia dekB
s paraMB
s. Se o tamanho da imagem for menor (ou até 1-2 MB) acima do código funcionando bem, mas se eu tiver uma imagem de tamanho acima de 4 MB ou 5 MB, oOOM
quadro será fornecido :(então trabalhei para resolver esse problema e finalmente fiz a melhoria abaixo no código do Fedor (todo o crédito ao Fedor por fazer uma solução tão boa) :)
Espero que isso ajude os amigos que enfrentam o mesmo problema!
para mais informações, consulte este
fonte
Acabei de encontrar este problema há alguns minutos. Eu o resolvi fazendo um trabalho melhor no gerenciamento do meu adaptador listview. Eu pensei que era um problema com as centenas de imagens de 50x50px que eu estava usando. Acontece que eu estava tentando aumentar minha exibição personalizada toda vez que a linha estava sendo exibida. Simplesmente testando para ver se a linha havia sido inflada, eliminei esse erro e estou usando centenas de bitmaps. Na verdade, isso é para um Spinner, mas o adaptador básico funciona da mesma forma para um ListView. Essa correção simples também melhorou bastante o desempenho do adaptador.
fonte
Passei o dia inteiro testando essas soluções e a única coisa que funcionou para mim foram as abordagens acima para obter a imagem e chamar manualmente o GC, que eu sei que não é necessário, mas é a única coisa que funcionou quando coloco meu aplicativo em testes de carga pesada alternando entre atividades. Meu aplicativo tem uma lista de imagens em miniatura em uma exibição de lista em (digamos atividade A) e quando você clica em uma dessas imagens, ele o leva para outra atividade (digamos atividade B) que mostra uma imagem principal para esse item. Quando eu alternava entre as duas atividades, acabava recebendo o erro OOM e o aplicativo se fechava.
Quando eu chegava na metade da lista, ele travava.
Agora, quando eu implemento o seguinte na atividade B, posso percorrer toda a lista sem problemas e continuar indo e indo e indo ... e é muito rápido.
fonte
Esse problema ocorre apenas em emuladores Android. Também enfrentei esse problema em um emulador, mas quando fiz o check-in de um dispositivo, ele funcionou bem.
Então, verifique o dispositivo. Pode ser executado no dispositivo.
fonte
Meus 2 centavos: resolvi meus erros de OOM com bitmaps por:
a) dimensionar minhas imagens por um fator de 2
b) usando a biblioteca Picasso no meu adaptador personalizado para um ListView, com uma chamada em getView, desta forma:
Picasso.with(context).load(R.id.myImage).into(R.id.myImageView);
fonte
use esse código para todas as imagens selecionadas em SdCard ou drewable para converter objetos de bitmap.
use o caminho da imagem no final de ImageData_Path.get (img_pos) .getPath () .
fonte
Geralmente, o tamanho da pilha do dispositivo Android é de apenas 16 MB (varia de acordo com o tamanho do dispositivo / SO, consulte os tamanhos de pilha da postagem ). Se você estiver carregando as imagens e cruzar o tamanho de 16 MB, lançará uma exceção de falta de memória, em vez de usar o Bitmap para carregar imagens do cartão SD ou de recursos ou mesmo da rede tentam usar getImageUri , carregar o bitmap requer mais memória ou você pode definir o bitmap como nulo se o trabalho foi feito com esse bitmap.
fonte
Todas as soluções aqui exigem a configuração de um IMAGE_MAX_SIZE. Isso limita os dispositivos com hardware mais poderoso e, se o tamanho da imagem for muito baixo, ele ficará feio na tela HD.
Eu criei uma solução que funciona com o meu Samsung Galaxy S3 e vários outros dispositivos, incluindo os menos poderosos, com melhor qualidade de imagem quando um dispositivo mais poderoso é usado.
O essencial é calcular o máximo de memória alocada para o aplicativo em um dispositivo específico e, em seguida, defina a escala para a menor possível, sem exceder essa memória. Aqui está o código:
Defino a memória máxima usada por este bitmap como 25% da memória máxima alocada; talvez seja necessário ajustá-lo às suas necessidades e verifique se esse bitmap está limpo e não fica na memória quando você terminar de usá-lo. Normalmente, eu uso esse código para executar a rotação da imagem (bitmap de origem e destino) para que meu aplicativo precise carregar 2 bitmaps na memória ao mesmo tempo, e 25% fornece um bom buffer sem ficar sem memória ao executar a rotação da imagem.
Espero que isto seja útil a alguém..
fonte
Isso
OutofMemoryException
não pode ser totalmente resolvido chamando oSystem.gc()
e assim por diante.Ao se referir ao Ciclo de Vida da AtividadeOs estados da atividade são determinados pelo próprio sistema operacional, sujeitos ao uso de memória para cada processo e à prioridade de cada processo.
Você pode considerar o tamanho e a resolução de cada uma das imagens de bitmap usadas. Recomendo reduzir o tamanho, redimensionar para uma resolução mais baixa, consultar o design das galerias (uma pequena imagem PNG e uma imagem original).
fonte
Esse código ajudará a carregar bitmap grande a partir de drawable
fonte
Bitmap.Config.ARGB_565
? Se a alta qualidade não for crítica.