2010-07-06 2 views
1

У меня есть приложение, которое использует фотографии, хранящиеся на SD-карте или непосредственно на телефоне.ImageView в Android Causing App to Crash

У меня 2 деятельности, которые, кажется, возникли какие-то проблемы (Acitives для просмотра и редактирования записи). Одна запись ссылается на фотографию, сохраняя URI, который дает местоположение связанной фотографии.

Когда я нажимаю на мой взгляд деятельности, я прохожу URI, а затем установите ImageView с помощью URI. Когда внутри View Activity, у меня есть опция меню, которая позволяет вам выполнить Edit Activity. Когда вы нажимаете «Изменить», я снова передаю URI фотографии и устанавливаю ImageView с помощью URI. Оба эти мероприятия прекрасно отображаются сами по себе.

Однако, когда я нажимаю кнопку «Назад», чтобы перейти от «Редактировать для просмотра», приложение выйдет из строя. Первоначально авария была OutOfMemory Exception. Я прошел мимо этого исключения, добавив вызов в ((BitmapDrawable)mImageView.getDrawable()).getBitmap().recycle() в функцию onPause в обоих действиях.

С кодом рециркуляции на месте, выполнение перемещается из Edit обратно в меню Вид, а затем просто падает где-то. Я прошел через функции жизненного цикла, и выполнение выполняется успешно, за исключением onCreate. Исполнение никогда не возвращается в CreateCreate.

Я знаю, что это что-то не связано с 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] 

После этого трассировки стека, если я продолжаю давить «Step Over» в Eclipse, трассировки стека заканчивается так:

Thread [<3> main] (Suspended) 
    ThreadGroup.uncaughtException(Thread, Throwable) line: 884 
    NativeStart.main(String[]) line: not available [native method] 

ответ

1

Я нашел способ преодолеть эту проблему.

Я смог найти это другое решение, частично благодаря ответу Януша. В классах View и Edit я добавил приватную переменную класса Bitmap (mBitmap). В onCreate я извлекаю и сохраняю URI для местоположения моего изображения. В onPause я перерабатываю растровое изображение. В onResume я обновил эту функцию, чтобы использовать новую переменную класса mBitmap (и я уверен, что есть лучший способ настроить Bitmap, чтобы каждый мог указать на это). Кроме того, с этим новым кодом я сначала столкнулся с крахом в классе Edit. Если вы перешли к редактору, затем нажмите кнопку «Главная», приложение будет разбиваться. Я обнаружил, что решение этой проблемы состояло в том, чтобы установить Bitmap образа изображения в null в Edit.onPause. Проблема заключалась в том, что imageView сохранял указатель на битмап, даже после того, как я переработал растровое изображение.См Android "Trying to use recycled bitmap" error?:

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 
} 
1

Если вы изменили действие с первого на второе, операция First будет приостановлена. Затем метод onPause будет перерабатывать битмап.
Если вы переключитесь назад с Activity Second на First Activity Сначала уже существует, и нет необходимости снова вызывать onCreateMethod. Вместо этого только метод onResume называется указанием активности, что он снова отображается на экране. В этот момент изображение пытается нарисовать изображение на экране, но поскольку изображение переработано, ваше приложение падает.

Если вам действительно нужно переработать битовую карту, вы должны сбросить его в методе onResume перед вызовом супер onResume метод вашей деятельности.

+0

Привет Януш, я ценю ответ. К сожалению, это не сработало для меня. Я все равно получаю тот же самый точный сбой при переходе с «Изменить обратно в режим просмотра». Я внесла следующие изменения: В onCreate я удалил настройку своего ImageView, и вместо этого я просто извлекаю и сохраняю URI для местоположения изображения. В onResume я добавил код для установки URI изображения на основе URI, который был сохранен в onCreate. Затем в onPause я вызываю переработку. – Michael

+0

Причина, по которой я это делаю, объясняется потоком выполнения, который я наблюдал в отладчике, который выглядит следующим образом: после запуска приложения я перехожу от главной страницы к виду, который вызывает эти функции: onCreate(), а затем onResume(). Когда я перехожу из «Вид в редактирование», поток выглядит следующим образом: «Просмотр onPause» вызывается (вызывается рециркуляция). Перемещение из меню «Редактировать назад» в «Вид» с помощью кнопки «Назад» вызывается функция View's onResume (вызываемый setImageURI). Это выполняется нормально, но позже приложение сработает. Есть ли лучший способ очистить ImageView, чем переработать? – Michael

+1

Еще одно наблюдение. Я захватил битмап, на который ссылается, вызывая ((BitmapDrawable) mImageView.getDrawable()). GetBitmap() и проверял адрес. Я заметил, что адрес был прежним до и после вызова на переработку. Я бы подумал, что после повторного использования адрес изменился бы. При возврате из «Правка» в «Вид» адрес является таким же. – Michael

0

Лучший способ отображения растрового изображения из аа потока и отображать ее в ImageView, не вызывая никаких сбоев является:

public void getImage(final ImageView imageView , final String picUrl) { 

    class GetImage extends AsyncTask<String,Void,Bitmap> { 
     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
     Log.i("Download","Profile Picture Downloaded"); 
     } 

     @Override 
     protected void onPostExecute(Bitmap b) { 
      super.onPostExecute(b); 
      imageView.setImageBitmap(b); 
     } 

     @Override 
     protected Bitmap doInBackground(String... params) { 
      URL url = null; 
      Bitmap image = null; 
      Bitmap finalImage=null; 
      try { 
       url = new URL(picUrl); 
       image = BitmapFactory.decodeStream(url.openConnection().getInputStream()); 
       finalImage= resize(image,120,120); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return finalImage; 
     } 
    } 

    GetImage gi = new GetImage(); 
    gi.execute(); 
} 

Методы имеет 2 параметра, то ImageView, что будет содержат наш Image и URL-адрес изображения, вам просто нужно вызвать метод с параметрами, и изображение будет отображаться.