Я испытываю стресс-тестирование приложения, которое состоит из кучи пользовательских представлений (фактически 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: не нашел точной причины, но я решил проблему, выполнив сбор мусора между видами переключения.
подумали ли вы об использовании параметров растровых изображений для импорта меньших изображений, которые занимают меньше данных изображения? Если у вас есть изображения с высоким разрешением (например, фотографии с камеры), никогда не нужно показывать пользователям полное разрешение изображения.
попробуйте сделать это, прежде чем импортировать растровое изображение
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;
}
Я предпочитаю какую-то "очистку" при работе с большим количеством изображений... Вы пытались деинициализировать (перерабатывать растровые изображения) загружаемые изображения, прежде чем удалять представление из макета?