Android, недостаточно памяти в пользовательском представлении - PullRequest
1 голос
/ 27 января 2011

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

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

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

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

Ниже приведен пример кода переключения моего просмотра, это переключение вперед на следующее представление.

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)

Кто-нибудь может подсказать, где я мог ошибиться?

РЕДАКТИРОВАТЬ: Не удалось найти точную причину, но я решил проблему, выполнив сборку мусора между переключением представлений.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2012

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

попробуйте сделать это перед импортом растрового изображения

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 голосов
/ 28 января 2011

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

...