Android, недостаточно памяти в пользовательском представлении

1

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

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

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

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

Ниже приведен пример кода переключения View View, это переключение вперед, в 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

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

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

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?
  • 0
    Нет, я не пытался, потому что из моего понимания это позволило бы системе удалять мои изображения из памяти, даже когда я их использую? Это правильное понимание? Это недопустимо для него, чтобы удалить изображения, пока мой вид все еще в фокусе.
Теги:
image
memory
memory-management

2 ответа

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
    К сожалению, изображения были для анимированной книги и были идеальными для экрана, на котором они отображались. Масштабирование изображений было невозможно. Однако я больше не работаю над проектом, поэтому надеюсь, что смогу принять один из этих ответов, который может оказаться полезным для других.
  • 0
    спасибо, что приняли и извините, я не смог помочь с вашим конкретным делом
Показать ещё 1 комментарий
0

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

  • 0
    Да, я пробовал это, к сожалению, я получаю нулевой указатель из-за попытки использовать только что переработанные растровые изображения. Я не очень понимаю, почему он все еще хотел бы использовать их, когда он уже был анимирован вне поля зрения (за кадром), а затем удален из макета. (Я переработал ПОСЛЕ удаления из макета, убивает мое приложение с нулевым указателем.
  • 0
    Вы должны отладить это поведение и взглянуть на идентификатор объекта, который вы используете при переключении. может быть, вы не создаете новый, а повторно используете старый? Вот что случилось со мной не так давно ...
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню