2012-04-04 3 views
1

память ПроблемаПросмотр пейджинга с большим количеством изображений, может ли он работать?

Так что я пишу приложение, которое должно быть в состоянии пролистать выносные, которые имеют один большие 640 х 480 изображений на верхнем и 3 изображения, которые являются частью галереи, которая лениться загружается. Следуя рекомендациям по разработке Google, это то, что они предлагают делать. Я могу прокрутить, возможно, 12 - 13 фрагментов, прежде чем он выйдет из строя из-за нехватки памяти. Я думаю, что в этой проблеме есть пара виновников.

1.) Я использую FragmentStatePager. Разве это не должно разрушать фрагменты, которые не просматриваются, когда память становится проблемой? Этого не происходит. Я думал, что это автоматический. Что я должен сделать, чтобы это произошло? Может ли это иметь какое-то отношение к тому, как я реализовал свой Фрагмент? Я делаю всю свою конфигурацию активности в onCreateView. Для тщательности я включил источник этого. Plain Vanilla здесь:

public static class MyAdapter extends FragmentStatePagerAdapter { 


     public MyAdapter(FragmentManager fm) { 
      super(fm);    
     } 

     @Override 
     public int getCount() { 
      return NUM_ITEMS; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      return InventoryDetailFragment.newInstance(position); 
     } 
    } 

2.) У меня есть метод, который пытается выяснить размер изображения, который должен быть загружен, не помещая его в памяти. Затем сжимает изображение при загрузке до требуемого размера. Это не успешно реализовано. Но я не уверен, что происходит не так.

private Bitmap downloadBitmap(String url, int width, int height) { 
    Bitmap bitmap = null; 
    int scale = 1; 
    try { 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     bitmap = BitmapFactory.decodeStream((InputStream)new URL (url).getContent(), null, options); 

     if (options.outHeight > height || options.outWidth > width) { 
      scale = (int) Math.max(((options.outHeight)/ height), ((options.outWidth)/ width));    } 

     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize = scale; 
     bitmap = BitmapFactory.decodeStream((InputStream)new URL (url).getContent(), null, o2); 
     cache.put(url, new SoftReference<Bitmap>(bitmap)); 


    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (Error e){ 
     Log.d("TEST", "Garbage Collector called!"); 
     System.gc(); 
    } 
    return bitmap; 
} 

Я пробовал все, что я знаю, как это сделать, но это выходит за рамки моего скудного понимания Android/Java. Пожалуйста помоги! Благодаря!

ответ

1

Есть несколько вещей, которые вам нужно изменить:

  1. Это ужасная идея: BitmapFactory.decodeStream((InputStream)new URL (url).getContent(), null, options); Вы получаете изображение из Интернета каждый раз, когда это выполняется (так дважды в коде, который вы отправили). Вместо этого вам необходимо загрузить изображение и кешировать его локально.

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

  3. И, наконец, ваш inSampleSize расчет неправильный. inSampleSize должно быть значением, которое является степенью двух, например. 1,2,4,8. Вы можете использовать логарифмы или простую бинарную логику, чтобы получить правильную, это то, что я использую, которая всегда будет декодирует с использованием по меньшей мере, 2 (только назвать это, если вы знаете, что изображение слишком велико):

-

int ratio = (int) Math.max((height/options.outHeight), (width/options.outWidth); //notice that they're flipped  
    for (int powerOfTwo = 64; powerOfTwo >=2; powerOfTwo = powerOfTwo >> 1) { //find the biggest power of two that represents the ratio 
    if ((ratio & powerOfTwo) > 0) { 
     return powerOfTwo; 
    } 
    } 
+0

Спасибо тонну. Я реализовал оба пункта 1 и 2. Я исключил 3 и просто вызвал createScaledBitmap для размеров, которые я хотел. Мне потребовалось некоторое время, чтобы вернуть загрузочные образы, выясняя, где на жизненном цикле их перезагрузить, но благодаря вам проблема была решена! – Rymnel

0

Если вы осознаете свою графику с opengl, это не будет учитываться в памяти. Другой ooption является использование

android:largeHeap="true" 

в манифесте. Может работать.

Вы использовали ddvm для поиска утечек памяти?

http://www.youtube.com/watch?v=_CruQY55HOk

+0

Это замечательно. Любое предложение о том, как это сделать? – Rymnel

+0

извините, im no opengl разработчик еще, но, возможно, у андроид-разработчика есть ответ? http://developer.android.com/guide/topics/graphics/opengl.html –

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