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
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.
}
}
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.
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.
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
- Catch OutOfMemoryError za pomocą try-catch
- ponieważ po tym błędzie Twoja aktywność może stać się niestabilna, uruchom ją ponownie.
- możesz wyłączyć animacje, aby użytkownik nie wiedział, że aktywność jest restartowana.
- 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!!
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