Outofmemeoryerror (viewpager + imageviews) - PullRequest
11 голосов
/ 21 февраля 2012

Я показываю 150+ изображений в пейджере, когда размер страницы пересек 70 приложение падает, все изображения загружаются из сети, и у меня произошла ошибка [ссылка]: Странно нехватка памяти при загрузке изображения вРастровый объект

, и я перерабатываю его всякий раз, когда перелистывание страниц достигает 4,

для 70-страничного приложения, занимающего 200 МБ памяти.

Мне нужна ваша помощь,как с этим справиться

я должен показывать все страницы со смахиванием ...

Я также использовал Runtime.getRuntime (). gc ();

- это любой способосвободить память, если память приложения достигает 50+ МБ

заранее спасибо

Ответы [ 6 ]

18 голосов
/ 01 марта 2012

Полное решение можно найти ниже, важные строки - те, что в методе destroyItem:

private class ContentPagerAdapter extends PagerAdapter {
    @Override
    public void destroyItem(View collection, int position, Object o) {
        View view = (View)o;
        ((ViewPager) collection).removeView(view);
        view = null;
    }

    @Override
    public void finishUpdate(View arg0) {
        // TODO Auto-generated method stub

    }
    @Override
    public int getCount() {
        return ids.length;
    }

    @Override
    public Object instantiateItem(View context, int position) {
        ImageView imageView = new ImageView(getApplicationContext());
        imageView.findViewById(R.id.item_image);
        imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(), ids[position]));

        ((ViewPager) context).addView(imageView);

        return imageView;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view==((ImageView)object);
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
        // TODO Auto-generated method stub
    }
    @Override
    public Parcelable saveState() {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void startUpdate(View arg0) {
        // TODO Auto-generated method stub

    }
4 голосов
/ 22 февраля 2012

Я думаю, что это происходит потому, что у вас утечка памяти, дважды проверьте свои переменные, не используйте статические переменные для чего-то большого, используйте final, когда это возможно, сделайте все члены приватными.

Я предлагаю вам сделать коммит (или сохранить текущий код), а затем попытаться сделать то, что я просил, и посмотреть, исправит ли он это.

пример кода позволит мне сообщить вам, если у вас есть утечки памяти, может быть, вы можете опубликовать код где-то, как на GitHub или Google Code

Итог: вы можете делать все правильно, но переменная по-прежнему содержит ссылку на ваши изображения, поэтому сборщик мусора не может их коснуться.

Я знаю, что у вас утечка памяти, но, пожалуйста, не пугайтесь, это случается с лучшими из лучших, потому что это так легко случиться.

ПРИМЕЧАНИЕ. Независимо от того, насколько большие данные, загружаемые из сетевых приложений, никогда не требовали большего, чем размер файла 1, при правильной обработке.

Спасибо

1 голос
/ 28 февраля 2012

Sheetal,

Посмотрев на ваш код, вы можете попробовать следующее:

@Override
public void destroyItem(View collection, int position, Object o) {
    Log.d("DESTROY", "destroying view at position " + position);
    View view = (View) o;
    ((ViewPager) collection).removeView(view);
    view = null;
}

Это должно освободить imageView для сборки мусора.

0 голосов
/ 22 февраля 2012

Sheetal,

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

В своей функции FragmentActivity я выполняю следующее в методе onCreate ():

pager = (ViewPager)findViewById(R.id.pager);
imageAdapter = new MyPagerAdapter(this, pager, theResources, listOfIds.pageBitMapIds);
imageAdapter.setRecentListener(this);
pager.setAdapter(imageAdapter);

Затем в моем PagerAdapter я делаю следующее:

@Override
public Object instantiateItem(ViewGroup container, int position) {
    MyFragment myFragment = new MyFragment(resources, resourceIds[position], recentListener, position);
    myFragments[position] = myFragment;
    return super.instantiateItem(container, position);
}

@Override
public Fragment getItem(int position) {
    return myFragments[position];
}

И затем я использую код в моем предыдущем ответе выше.

Это, очевидно, не полный код, и он был адаптирован из моегофактический код, но он должен дать вам хорошее представление о том, что и где делать.

Mark

0 голосов
/ 21 февраля 2012

Sheetal,

У меня нет кода передо мной, но он должен быть похож на следующий:

public class MyFragment extends Fragment {
  private Resources resources;  // I load my images from different resources installed on the device
  private int id;

  public MyFragment() {
    setRetainInstance(true); // this will prevent the app from crashing on screen rotation
  }

  public MyFragment(Resources resources, int id) {
    this();  // this makes sure that setRetainInstance(true) is always called
    this.resources = resources;
    this.id = id;
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ImageView imageView = (ImageView)inflater.infale(R.layout.fragmentview, container, false);
    imageView.setImageBitmap(BitmapFactory.decodeResource(resources, id));

    return imageView;
  }
}

Это в значительной степени не в моей голове, так что это может быть не совсем точно, но это довольно близко.

Если вам нужна дополнительная помощь, просто кричите, не забудьте пометить этот ответ как помогший вам:).

0 голосов
/ 21 февраля 2012

Загружаете ли вы изображения с помощью метода просмотра onCreateView ()?

Фреймворк, похоже, заботится о требованиях к управлению памятью, делая это таким образом. Я попытался загрузить свои изображения в мой FragmentPageAdapter, передав их в предварительно загруженный конструктор Fragment или в качестве части метода instaniateItem Fragment, но оба эти вопроса дали мне проблему, с которой вы столкнулись. В конце я передал информацию, необходимую для загрузки каждого изображения, в конструктор Fragment, а затем использовал эти детали в методе onCreateView ().

Mark

...