2011-01-27 4 views
1

Я испытываю стресс-тестирование приложения, которое состоит из кучи пользовательских представлений (фактически 3), которые хранятся в frameLayout.Android, из памяти в пользовательском представлении

Только два одновременно проводятся. У меня есть вид 1, добавьте вид два, анимируйте 1 и анимируйте в 2, затем удалите 1, и наоборот, если я пойду взад и вперед, взгляды.

Каждый вид загружает большое количество данных изображения, когда он будет создан, используя следующий метод:

mBmp[background] = BitmapFactory.decodeStream(context.getAssets().open("view1_background.png")); 

Ниже приведен пример с моей точки зрения переключения кода, это переключение вперед, к NEXTVIEW.

currView.startAnimation(AnimClass.outToLeftAnimation(null)); 
    intView++; 
    nextView = ViewFactory.getInstance(this, intView, viewInitializer); 
    mainLayout.addView(nextView, 0); 
    nextView.startAnimation(AnimClass.inFromRightAnimation(this)); 
    mainLayout.removeViewInLayout(currView); 
    currView = nextView; 
    nextView = null; 

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

Проблема заключается в том, что если я быстро переключу виды, я могу заставить его перестать поддерживать (даже если я отключу кнопки до завершения анимации слайда), и после нескольких переключений я потеряю большую часть изображения в представлении и просто заканчиваются одним или двумя из самых маленьких изображений. Она не показывает каких-либо ошибок, когда это происходит, за исключением следующих сообщений (одно за изображение в этой точке зрения):

01-27 13:52:00.730: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.011: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 425984 
01-27 13:52:01.011: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 1187840 
01-27 13:52:01.011: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.093: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.128: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 425984 
01-27 13:52:01.144: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 1187840 
01-27 13:52:01.179: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.245: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 425984 
01-27 13:52:01.261: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.277: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 1187840 
01-27 13:52:01.343: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.363: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 425984 
01-27 13:52:01.409: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 1187840 
01-27 13:52:01.429: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 
01-27 13:52:01.511: DEBUG/skia(23064): ------- imageref_ashmem create failed <(null)> 139264 

Если я переключаю взгляды, он делает то же самое на каждом представлении. Мне кажется, что мой код переключения просмотров не отменяет представления при их удалении или удалении изображений (растровых изображений) после удаления представления.

Если я затем использовать намерение вернуться к своей основной деятельности я получаю следующее:

Surface E Surface (identity=4810) requestBuffer(0, 00000033) returneda buffer with a null handle 
Surface E getBufferLocked(0, 00000033) failed (Out of memory) 
Surface E dequeueBuffer failed (Out of memory) 
ViewRoot E OutOfResourcesException locking surface 
ViewRoot E android.view.Surface$OutOfResourcesException 
ViewRoot E  at android.view.Surface.lockCanvasNative(Native Method) 
ViewRoot E  at android.view.Surface.lockCanvas(Surface.java:314) 
ViewRoot E  at android.view.ViewRoot.draw(ViewRoot.java:1363) 
ViewRoot E  at android.view.ViewRoot.performTraversals(ViewRoot.java:1172) 
ViewRoot E  at android.view.ViewRoot.handleMessage(ViewRoot.java:1749) 
ViewRoot E  at android.os.Handler.dispatchMessage(Handler.java:99) 
ViewRoot E  at android.os.Looper.loop(Looper.java:123) 
ViewRoot E  at android.app.ActivityThread.main(ActivityThread.java:4627) 
ViewRoot E  at java.lang.reflect.Method.invokeNative(Native Method) 
ViewRoot E  at java.lang.reflect.Method.invoke(Method.java:521) 
ViewRoot E  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871) 
ViewRoot E  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629) 
ViewRoot E  at dalvik.system.NativeStart.main(Native Method) 

Можно ли предположить, где я мог бы пойти не так?

EDIT: Не нашли точной причины, но я решил проблему, выполнив сбор мусора между переключающими видами.

+0

Гамида, ты пробовал использовать SoftReference? – 100rabh

+0

Нет, я не пробовал, потому что из моего понимания это позволило бы системе удалить мои изображения из памяти, даже когда я их использую? Это правильное понимание? Для него неприемлемо удалить изображения, пока мой взгляд все еще находится в фокусе. – Hamid

ответ

0

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

попробовать сделать это, прежде чем импортировать растровое изображение

Options options = new Options();    
options.inJustDecodeBounds = true; 

BitmapFactory.decodeFile(context.getAssets().open("view1_background.png"), options); 

options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

Log.i(getClass().getSimpleName(), 
      "height: " + options.outHeight + 
      "\nwidth: " + options.outWidth + 
      "\nmimetype: " + options.outMimeType + 
      "\nsample size: " + options.inSampleSize); 

options.inJustDecodeBounds = false; 

mBmp[background] = BitmapFactory.decodeStream(context.getAssets().open("view1_background.png")); 

где размер выборки определяется следующим образом:

public static int calculateInSampleSize(Options options, int reqWidth, int reqHeight) 
{ 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    while (height/inSampleSize > reqHeight || width/inSampleSize > reqWidth) 
    { 
     if (height > width) 
     { 
      inSampleSize = height/reqHeight; 
      if (((double)height % (double)reqHeight) != 0) 
      { 
       inSampleSize++; 
      } 
     } 
     else 
     { 
      inSampleSize = width/reqWidth; 
      if (((double)width % (double)reqWidth) != 0) 
      { 
       inSampleSize++; 
      } 
     } 
    } 
    return inSampleSize; 
} 
+0

К сожалению, изображения были предназначены для анимированной книги и были идеальны для экрана, на котором они были показаны. Масштабирование изображений было невозможным. Однако я больше не работаю над проектом, поэтому надеюсь, что смогу принять один из этих ответов, который может быть полезен другим. – Hamid

+0

спасибо, что согласился и извините, я не смог помочь с вашим точным случаем –

+0

Нет проблем. Спасибо, что дал ему шанс, даже после оригинального вопроса. Без сомнения, ваш ответ станет полезным для других. – Hamid

0

Я предпочитаю какую-то «очистку» при работе с большим количеством изображений ... Вы пытались деинициализировать (перерабатывать растровые изображения) загружаемые изображения, прежде чем удалять представление из макета?

+0

Да, я пробовал это, к сожалению, я получаю нулевой указатель из-за попытки использовать растровые изображения, которые только что были переработаны.Я не понимаю, почему он все равно захочет использовать их, когда он уже был анимирован вне поля зрения (вне экрана), а затем удален из макета. (Я переработал ПОСЛЕ удаления из макета, убил мое приложение нулевым указателем. – Hamid

+0

Вы должны отладить это поведение и взглянуть на идентификатор объекта, который вы используете при переключении. Возможно, вы не создаете новое, а повторно используете старый? что случилось со мной совсем недавно ... – WarrenFaith

+0

Ну, у меня есть 3 объекта вида (prev, current и next), когда я переключаюсь назад или вперед, я создаю новый вид в prev или next соответственно, переключая ток с prev или next , затем удалите ток и назначьте prev или рядом с текущим. – Hamid

Смежные вопросы