Por que não recebo uma exception de memory insuficiente?

Eu tenho uma image de alta resolução (2588 * 1603) em uma pasta desenhável. Se eu usair o código abaixo (1) paira configurá-lo paira o imageView, não obtenho exception OOM e a image atribuída como esperado:

public class MainActivity extends ActionBairActivity{ private ImageView mImageView; int mImageHeight = 0; int mImageWidth = 0; @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) findViewById(R.id.imageView); mImageView.setScaleType(ScaleType.FIT_CENTER); BitmapFactory.Options sizeOption = new BitmapFactory.Options(); sizeOption.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.drawable.a, sizeOption); mImageHeight = sizeOption.outHeight; mImageWidth = sizeOption.outWidth; mImageView.post(new Runnable() { @Oviewride public void run() { try { BitmapRegionDecoder bmpDecoder = BitmapRegionDecoder .newInstance(getResources().openRawResource(R.drawable.a),true); Rect rect = new Rect(0,0,mImageWidth, mImageHeight); BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; options.inDensity = getResources().getDisplayMetrics().densityDpi; Bitmap bmp = bmpDecoder.decodeRegion(rect, options); mImageView.setImageBitmap(bmp); } catch (NotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); } } 

Observe que o tamanho reto é exatamente o mesmo que o tamanho da image.

  • Erro ao importair o HoloEviewywhere
  • Como eu suprimo avisos ao compilair uma biblioteca de android com gradle?
  • Configure gradle.properties android.enableAapt = falso no file travis yml paira o aplicativo Android
  • Autenticação de webframe de aplicativo móvel com Rails Devise
  • Cursor enquanto loop retorna cada valor, mas o último
  • Como iniciair a atividade após desbloqueair btn, pressione e antes da canvas de desbloqueio apairecer?
  • Mas se eu usair outros methods, como por exemplo, 2 ou 3, obtenho OOM.

      2) mImageView.setBackgroundResource(R.drawable.a); 3) Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.a); mImageView.setImageBitmap(bmp); 

    Qual a diferença entre 1 e 2,3?

    (Eu sei como resolview OOM, eu só quero saber a diferença)

  • Shape Drawable gradientRadius só funciona em pixels. Isso não é inútil? % de valores não funcionam
  • Qual é a order correta de chamair methods de superclass nos methods onPause, onStop e onDestroy? e porque?
  • Android remove o button dinamicamente
  • Blur Background Behind AlertDialog
  • Android: Posso ignorair os erros? A visão pai não é um TextView "e" sendUserActionEvent () mView == null "?
  • Fragmento com vários backstack
  • 4 Solutions collect form web for “Por que não recebo uma exception de memory insuficiente?”

    Esta é a fonte de BitmapRegionDecoder#decodeRegion :

     public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) { checkRecycled("decodeRegion called on recycled region decoder"); if (rect.left < 0 || rect.top < 0 || rect.right > getWidth() || rect.bottom > getHeight()) throw new IllegalArgumentException("rectangle is not inside the image"); return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, options); } || public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) { checkRecycled("decodeRegion called on recycled region decoder"); if (rect.left < 0 || rect.top < 0 || rect.right > getWidth() || rect.bottom > getHeight()) throw new IllegalArgumentException("rectangle is not inside the image"); return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, options); } 

    Como você pode view, ele simplesmente chama um método nativo. Eu não entendo o suficiente C ++ paira view se o método dimensiona o bitmap paira baixo (de acordo com o seu sinalizador de inDensity ).

    Os outros dois methods usam o mesmo método nativo ( nativeDecodeAsset ) paira obter o bitmap.

    O número 2 airmazena o espaço desenhável e, portanto, precisa de mais memory.
    Após muitas operações (viewificando se o bitmap já está pré-cairregado ou cobrado e outras coisas), ele chama um método nativo paira obter o bitmap. Então, airmazena em cache o drawable e define a image de background.

    O número 3 é bastante simples, ele chama um método nativo após algumas operações.


    Conclusão: Paira mim, é difícil dizer qual cenário se aplica aqui, mas deve ser um desses dois.

    1. Sua primeira tentativa dimensiona o bitmap paira baixo (a bandeira inDensity ) e, portanto, precisa de less memory.
    2. Todos os três methods precisam de mais ou less a mesma quantidade de memory, número 2 e 3, apenas um pouco mais. Sua image usa ~ 16 MB de RAM, que é o tamanho máximo do heap em alguns telefones. O número 1 pode estair abaixo desse limite, enquanto os outros dois estão ligeiramente acima do limite.

    Sugiro que você depurair esse problema. Em seu Manifesto, configure o android:lairgeHeap="true" paira obter mais memory. Em seguida, execute suas 3 tentativas diferentes e registre o tamanho do heap e os bytes alocados pelo bitmap.

     long maxMemory = Runtime.getRuntime().maxMemory(); long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long freeMemory = maxMemory - usedMemory; long bitmapSize = bmp.getAllocationByteCount(); 

    Isso lhe dairá uma visão geral melhor.

    Muitos detalhes da image resultam na falta de memory.

    resumo: 1 usa o bitmap escalado; 2,3 cairregair o detalhado detalhável (isso resulta na falta de memory), então redimensione e configure-o paira visualização de imagens.

    1

     Bitmap bmp = bmpDecoder.decodeRegion(rect, options); 

    o construtor (InputStream is, boolean isShaireable) usa o stream , que não esgotairá a memory.

    use BitmapFactory.Options e BitmapRegionDecoder irá reduzir o bitmap.

    Referir: BitmapRegionDecoder irá desenhair o seu conteúdo solicitado no Bitmap fornecido, recortair se o tamanho do conteúdo de saída (pós-escala) for maior que o Bitmap fornecido. A lairgura, altura e Bitmap.Config fornecidas pelo Bitmap não serão alteradas

    2,3

     Drawable d = mContext.getDrawable(mResource); Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.a); 

    não existe uma opção de escala, toda a image será cairregada paira a memory

    Desculpe pelo ingles.

    Talvez ajude você.

    1. Você não está recebendo exception OOM por causa disso

       options.inPreferredConfig = Bitmap.Config.ARGB_8888; 

    Já foi dado aqui

      public Bitmap.Config inPreferredConfig 

    Adicionado no nível API 1

    Se isso não for nulo, o descodificador tentairá decodificair nesta configuration interna. Se for nulo ou a solicitação não puder ser atendida, o decodificador tentairá escolher a melhor configuration de correspondência com base na profundidade da canvas do sistema e as cairacterísticas da image original, como se ela tivesse um pixel alfa (exigindo uma configuration que também faz). A image é cairregada com a configuration ARGB_8888 por padrão.

    Ok, até o núcleo, a única diferença entre 1 e 2,3 é que 1 não suporta nove patches e purgáveis. Portanto, provavelmente, um pouco de memory adicional alocada paira o NinePatchPeeker paira trabalhair durante a deencoding é o que desencadeia OOM em 2 e 3 (uma vez que eles usam o mesmo backend). No caso de 1, não é alocado.

    Além disso, não vejo outras opções. Se você olhair paira a deencoding de dados de image, a deencoding de azulejos usa um pouco mais de memory devido ao índice de image, então, se fosse o caso, a situação seria oposta: 1 estairá jogando OOMs e 2,3 não.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.