Wyłapywanie błędu w dekodowaniu bitmapy

Czy jest to dobra praktyka, aby złapać OutOfMemoryError nawet próbowałeś kilka sposobów, aby zmniejszyć zużycie pamięci? A może po prostu nie łapiemy wyjątku? Który z nich jest lepszym treningiem?

try {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(file, options);
} catch (OutOfMemoryError e) {
    e.printStackTrace();
}

Thanks

Author: bitbybit, 2011-08-21

4 answers

Dobrze jest złapać go raz i dać kolejną szansę. Złap go i zadzwoń System.gc() i spróbuj ponownie dekodować. Istnieje duże prawdopodobieństwo, że będzie działać po wywołaniu System.gc().

try {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(file, options);
 } catch (OutOfMemoryError e) {
    e.printStackTrace();

    System.gc();

    try {
        bitmap = BitmapFactory.decodeFile(file);
    } catch (OutOfMemoryError e2) {
      e2.printStackTrace();
      // handle gracefully.
    }
}
 35
Author: Ronnie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-10 10:05:05

Zrobiłem coś takiego: łapię błąd tylko po to, aby spróbować skalować obraz, aż zadziała. Ostatecznie nie może w ogóle działać; następnie zwraca null; w przeciwnym razie, w przypadku sukcesu, zwraca bitmapę.

Na Zewnątrz decyduję, co zrobić z bitmapą, czy jest null, czy nie.

// Let w and h the width and height of the ImageView where we will place the Bitmap. Then:

// Get the dimensions of the original bitmap
BitmapFactory.Options bmOptions= new BitmapFactory.Options();
bmOptions.inJustDecodeBounds= true;
BitmapFactory.decodeFile(path, bmOptions);
int photoW= bmOptions.outWidth;
int photoH= bmOptions.outHeight;

// Determine how much to scale down the image. 
int scaleFactor= (int) Math.max(1.0, Math.min((double) photoW / (double)w, (double)photoH / (double)h));    //1, 2, 3, 4, 5, 6, ...
scaleFactor= (int) Math.pow(2.0, Math.floor(Math.log((double) scaleFactor) / Math.log(2.0)));               //1, 2, 4, 8, ...

// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds= false;
bmOptions.inSampleSize= scaleFactor;
bmOptions.inPurgeable= true;

do
{
    try
    {
        Log.d("tag", "scaleFactor: " + scaleFactor);
        scaleFactor*= 2;
        bitmap= BitmapFactory.decodeFile(path, bmOptions);
    }
    catch(OutOfMemoryError e)
    {
        bmOptions.inSampleSize= scaleFactor;
        Log.d("tag", "OutOfMemoryError: " + e.toString());
    }
}
while(bitmap == null && scaleFactor <= 256);

if(bitmap == null)
    return null;

Na przykład, przy obrazie 3264x2448, pętla powtarza się 2 razy w moim telefonie, a następnie działa.

 9
Author: jsanmarb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-13 13:05:20

Chcesz go złapać, jeśli chcesz wyświetlić mniejszy obraz / inny obraz / pokazać niestandardowy komunikat o błędzie dla użytkownika. Twoje opakowanie dostępu do obrazu może wychwycić te błędy i zwrócić niektóre niestandardowe kody błędów zdefiniowane w kodzie; Twoja aktywność, która używa tego kodu, może zdecydować, co zrobić z kodem błędu - ostrzec użytkownika, zmusić go do wyjścia z lepszym Komunikatem o błędzie niż ten, który zapewnia system android, itp.

Btw, nie używasz zmiennej options w swoim przykładowy kod.

 0
Author: chocolat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-21 14:18:38

Chociaż może nie być dobrym pomysłem, aby złapać OutOfMemoryError za pomocą try-catch. Ale czasami nie masz wyboru, ponieważ wszyscy z nas nienawidzą awarii aplikacji. Więc, co możesz zrobić to

  1. Catch OutOfMemoryError za pomocą try-catch
  2. ponieważ po tym błędzie Twoja aktywność może stać się niestabilna, uruchom ją ponownie.
  3. możesz wyłączyć animacje, aby użytkownik nie wiedział, że aktywność jest restartowana.
  4. możesz umieścić dodatkowe dane, aby wiedzieć, że aplikacja została zawieszona podczas poprzedni bieg.

Jak ja to zrobiłem:

    try {
        //code that causes OutOfMemoryError
    } catch (Exception e) {
        // in case of exception handle it
        e.printStackTrace();
    } catch (OutOfMemoryError oome)
    {
        //restart this activity
        Intent i=this.getIntent();
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); //disable animation

        //EXTRA_ABNORMAL_SHUTDOWN is user defined       
        i.putExtra(this.EXTRA_ABNORMAL_SHUTDOWN, true);
        //put extra data into intent if you like

        finish(); //and finish the activity
        overridePendingTransition(0, 0);
        startActivity(i); //then start it(there is also restart method in newer API)
        return false;
    }

A potem po wykonaniu czynności można wznowić (coś w tym stylu):

boolean abnormalShutdown=getIntent().getBooleanExtra(this.EXTRA_ABNORMAL_SHUTDOWN, false);
if (abnormalShutdown)
{
    //Alert user for any error
    //get any extra data you put befor restarting.
}

To podejście uratowało moją aplikację. Mam nadzieję, że tobie też pomoże!!

 0
Author: prodev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-23 06:29:03