0

Я читал так много потоков в StackOverflow, но не смог найти решение для моей проблемы. Я пытался решить проблему в течение прошлой недели, но не мог понять это. Было бы замечательно, если бы кто-то может помочь мне,Viewpager - OutOfMemory - используя фрагменты

Вот проблема,

У меня есть около 50 изображений и я использую ViewPager и фрагментов, чтобы пользователю перелистывать изображения. Все изображения размером 250 * 350, не более 20 Кбайт на изображение. На Swyping тридцатые-35 изображение я получаю OutOfMemory исключение .. Вот трассировки стека,

09-07 16:30:09.126: E/MessageQueue-JNI(1023): java.lang.OutOfMemoryError 
09-07 16:30:09.126: E/MessageQueue-JNI(1023): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
09-07 16:30:09.126: E/MessageQueue-JNI(1023): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:683) 
09-07 16:30:09.126: E/MessageQueue-JNI(1023): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:513) 
09-07 16:30:09.126: E/MessageQueue-JNI(1023): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:541) 
09-07 16:30:09.126: E/MessageQueue-JNI(1023): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:571) 

Вот код MyGallery.java,

@Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     List<Fragment> fragments = getFragments(); 

     pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments); 
     ViewPager pager = (ViewPager) findViewById(R.id.viewpager); 
     pager.setOffscreenPageLimit(2); 
     pager.setAdapter(pageAdapter); 
    } 



private List<Fragment> getFragments() { 
    List<Fragment> fList = new ArrayList<Fragment>(); 
    String picture_book = ""; 
    for (int i = 1; i <= 50; i++) { 
     picture_book = "picture" + i; 
     fList.add(MyGallery_Fragment.newInstance(picture_book)); 
    } 
    return fList; 
} 

private class MyPageAdapter extends FragmentStatePagerAdapter { 
    private List<Fragment> fragments; 

    public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) { 
     super(fm); 
     this.fragments = fragments; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return this.fragments.get(position); 
    } 

    @Override 
    public int getCount() { 
     return this.fragments.size(); 
    } 
} 

А вот класс MyGaller_Fragment,

public static final MyGallery_Fragment newInstance(String picture) { 

     MyGallery_Fragment f = new MyGallery_Fragment(); 
     contextForDialog = f.getActivity(); 
     Bundle bdl = new Bundle(); 
     bdl.putString("picture", picture); 

     f.setArguments(bdl); 
     return f; 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     context = activity.getApplicationContext(); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     picture = getArguments().getString("picture"); 

     View v = inflater 
       .inflate(R.layout.mygallery_fragment, container, false); 


     picture_img = (ImageView) v.findViewById(R.id.picture_iv); 
     picture_resID = getResources().getIdentifier(picture, "drawable", 
       context.getPackageName()); 


     picture_biticon = BitmapFactory.decodeResource(getResources(), 
       picture_resID); 
     picture_img.setImageBitmap(picture_biticon); 

     return v; 
    } 
} 

Это то, что я пытался,

  1. Я использовал FragmentPagerAdapter и был изменен на FragmentStatePagerAdapter как упоминалось here .. Я думал, что FragmentStatePagerAdapter просто сохраняет вид фрагментов прямо слева и справа от текущего показанного элемента и автоматически уничтожает другие элементы .. но это не помогло проблема,

  2. Я даже установил setOffScreenPageLimit в 2, так что старые фрагменты будут уничтожены .. но это тоже не решило.

  3. Я попытался уничтожить Bitmap после присвоения значения, но получил ту же ошибку.

  4. Я также попробовал этот код в классе MyGallery_Fragment,

    @Override public void onDestroy() { super.onDestroy(); Drawable drawable = picture_img.getDrawable(); if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; picture_biticon = bitmapDrawable.getBitmap(); picture_biticon.recycle(); } }

  5. Я тестировал приложение в примечании II, и это показывает outofmemory между любым из прикосновения изображений тридцатого-35, но тот же код работая отлично в моем недавно купленном Moto E.

Было бы здорово, если бы кто-нибудь мог помочь мне решить эту проблему.

ответ

0

Существует статья о загрузке растровых изображений на сайте developer.android.com. Вы можете думать об этом как о лучших методах. Вы можете найти его на http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

В нем рассказывается о различных механизмах загрузки растровых изображений. Вы считали это?

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

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

@Override 
    public Fragment getItem(int position) { 
     String picture_book = "picture" + i; 
     return MyGallery_Fragment.newInstance(picture_book); 
    } 

    @Override 
    public int getCount() { 
     return 50; 
    } 
+0

Спасибо .. Я уже посмотрел на сайт разработчика Android, о котором вы упоминали. Речь идет о обработке больших растровых изображений, но в моем случае у меня есть все изображения размером 250 * 350 и размером не более 20 КБ. да, я создаю несколько экземпляров фрагментов, но я не вижу никаких проблем, если загружаю только TextView .. Проблема только в Imageview. – Naveen

1

Хранение этого количества фрагмента - плохая идея - вы не должны этого делать. Просмотр пейджера соседей кэшей для анимации, и этого достаточно. Вместо фрагмента. вам следует подумать о сохранении списка моделей, которые необходимы для создания определенных представлений и создания фрагментов «на лету» в вашем адаптере.

Другие советы:

устройства Samsung обрабатывать память иначе, чем другие устройства, у меня были аналогичные проблемы на S3 и S4. Также вы должны знать, что просмотр пейджера загружает по умолчанию соседние текущие фрагменты, поэтому, если вы установите ограничение экрана на 2, это означает, что viewpager будет загружать также два фрагмента слева от текущего и двух справа, поэтому вам следует рассмотреть возможность оставить значение по умолчанию значение (1).

О размере файла - если это 30 КБ в файле, это не значит, что он будет использовать ту же сумму в памяти графической карты - обычно это намного больше. Вы должны подумать о том, чтобы перемасштабировать их во время выполнения, прежде чем нажимать на нее, как это заметил Вино. Также вы можете попробовать установить android: largeHeap = "true" в вашем явном узле приложения.

+0

Спасибо за ваш совет. Поскольку я использую [FragmentStatePagerAdapter] (http://developer.android.com/reference/android/support/v13/app/FragmentStatePagerAdapter.html), я думал, что фрагменты будут повторно использованы. Пожалуйста, дайте мне знать, что я должен изменить, чтобы избежать этого? Любые учебники были бы очень полезны. – Naveen

+0

Пример Google: http://developer.android.com/training/animation/screen-slide.html – 3mpty

+0

Да, я посмотрел пример, предоставленный вами. Также я [проверил это] (http: // developer. android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html). Даже в этом примере они создают новые экземпляры фрагментов. Я полагаю, что Android позаботится о том, чтобы уничтожить фрагменты, которых нет в представлении. Пожалуйста, поправьте меня, если мое понимание неверно. – Naveen

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