У меня есть приложение, которое использует фотографии, сохраненные или на SD-карте или на непосредственно по телефону.
У меня есть 2 Операции, которые, кажется, имеют некоторую проблему (Acitives для Просмотра и Редактирования записи). Рекордные ссылки сингла фотография путем хранения URI, который дает местоположение связанной фотографии.
Когда я нажимаю на свое действие Представления, я передаю URI и затем устанавливаю ImageView с помощью URI. Когда в Действии Представления, у меня есть пункт меню, который позволяет Вам достигать Действия Редактирования. Когда Вы нажимаете Edit, я снова передаю URI фотографии и устанавливаю ImageView с помощью URI. Обе из этих операций дисплей, прекрасный самостоятельно.
Однако, когда я нажимаю Кнопку "Назад" для перемещения от Редактирования до Представления, сбоев приложения. Первоначально катастрофический отказ был Исключением OutOfMemory. Я закончил это исключение путем добавления вызова к ((BitmapDrawable)mImageView.getDrawable()).getBitmap().recycle()
в onPause функционируют в обеих операциях.
С перерабатывать кодом на месте, перемещениями выполнения от Редактирования назад для Просмотра, и затем просто отказывает где-нибудь. Я ступил через функции жизненного цикла, и выполнение удается успешно, за исключением onCreate. Выполнение никогда не достигает onCreate снова.
Я знаю, что это - что-то связанное с ImageView, потому что, когда я удаляю ImageView из расположения, по моему мнению, действие, катастрофического отказа больше не происходит.
Вот начальное отслеживание стека, когда катастрофический отказ происходит:
Thread [<3> main] (Suspended (exception RuntimeException))
ViewRoot.draw(boolean) line: 1356
ViewRoot.performTraversals() line: 1097
ViewRoot.handleMessage(Message) line: 1613
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 123
ActivityThread.main(String[]) line: 4203
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 791
ZygoteInit.main(String[]) line: 549
NativeStart.main(String[]) line: not available [native method]
После этого отслеживания стека, если я продолжаю продвигать, "Переступают" в Eclipse, отслеживание стека заканчивается как это:
Thread [<3> main] (Suspended)
ThreadGroup.uncaughtException(Thread, Throwable) line: 884
NativeStart.main(String[]) line: not available [native method]
Я нашел способ решить эту проблему.
Я смог найти это другое решение отчасти благодаря ответу Януша. В моих классах View и Edit я добавил приватную переменную класса Bitmap (mBitmap). В onCreate я получаю и сохраняю URI для местоположения моего изображения. В onPause я перерабатываю битмап. В onResume я обновил эту функцию, чтобы использовать новую переменную класса mBitmap (и я уверен, что есть лучший способ настройки Bitmap, так что все не стесняйтесь указать на него). Кроме того, с этим новым кодом я столкнулся с проблемой сбоя в классе Edit. Если вы заходили в Edit, а затем нажимали кнопку "Home", приложение аварийно завершало работу. Я обнаружил, что решением этой проблемы является установка Bitmap представления изображения на null в Edit.onPause. Проблема заключалась в том, что imageView сохранял указатель на битмап, даже после того, как я переработал битмап. См. Ошибка Android "Trying to use recycled bitmap?":
protected void onResume()
{
mBitmap = null;
try
{
mBitmap = Bitmap.createBitmap(Media.getBitmap(this.getContentResolver(), mPicUri));
}
catch(Exception e)
{}
mImageView.setImageBitmap(mBitmap);
mImageView.setAdjustViewBounds(true);
mImageView.setMaxHeight(100); //purposely showing image as 100x100 picture
mImageView.setMaxWidth(100);
mImageView.invalidate();
super.onResume();
}
protected void onCreate()
{
mPicUri = //the picuture location URI
}
protected void onPause()
{
mBitmap.recycle();
mImageView.setImageBitmap(null); //in my Edit class
}
Если вы переходите с первого действия на второе, первое действие будет приостановлено. Затем метод onPause перезапустит растровое изображение.
Если вы переключитесь с «Второе действие» на «Первое», первое действие уже существует, и нет необходимости снова вызывать onCreateMethod. Вместо этого вызывается только метод onResume, сообщающий активности, что она снова отображается на экране. В этот момент imageview пытается нарисовать изображение на экране, но из-за того, что изображение переработано, ваше приложение вылетает.
Если вам действительно нужно переработать растровое изображение, вы должны сбросить его в методе onResume перед вызовом метода super onResume вашего действия.