Проблемы с памятью - фрагменты - PullRequest
4 голосов
/ 03 апреля 2012

Я недавно провела рефакторинг приложения и заменила ViewFlipper на FrameLayout, в котором я переключаюсь между фрагментами.

Каждый раз, когда пользователь запрашивает одно из представлений:

    public void showLibraryOf(long publisherId) {
        library = new DownloadLibraryFragment(id, viewFactory());

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.container, library);
        ft.commit();

        library.setAdapterObserver(this);
    }

    public void showMyLibraryOf(long publisherId) {
        myLibrary = new MyLibraryFragment(id, viewFactory());

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.container, myLibrary);
        ft.commit();
    }

    public void showHelp() {
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.container, new HelpFragment());
        ft.commit();
    }

Я создаю новый фрагмент и заменяю старый. При удалении с экрана вызывается onDestroy, но память, занятая растровыми изображениями, которые я загружаю на экран, не удаляется, поэтому приложение падает после некоторого обмена между фрагментами.

Я также пытался удалить ссылки на onDestroy

@Override
public void onDestroyView() {
    destroy();
    super.onDestroyView();   
    adapter.clear();
    adapter.clearObservers();
    adapter.notifyDataSetChanged();

    view.setAdapter(new ArrayAdapter<Journal>(getActivity(), 0));

    adapter = null;
    view = null;
}

Но память продолжает расти.

Кто-нибудь знает какое-нибудь решение? возможно повторное использование фрагментов? эффективно уничтожить это? Я слушаю.

1 Ответ

6 голосов
/ 21 апреля 2012

Я забыл, из какого вопроса stackoverflow я первоначально извлек этот код, но один метод, который, кажется, работает хорошо, - переопределить onAttachFragment из FragmentActivity, а затем сохранить WeakReference для каждого переданного фрагмента. Затем,вместо использования метода замены FragmentTransaction вы перерабатываете все фрагменты (в зависимости от ситуации).

Вот пример дополнительных членов и методов для FragmentActivity, который создает фрагмент по умолчанию в onCreate иреагирует на изменения через onNewIntent:

private List<WeakReference<Fragment>> mFragments = 
    new ArrayList<WeakReference<Fragment>>();

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

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.add(R.id.fragment_container, MyFragment.newInstance("default"));
    ft.commit();
}

@Override
protected void onNewIntent(Intent intent) {
    setIntent(intent);
    String section = intent.getStringExtra("section");
    recycleFragments();
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.add(R.id.fragment_container, MyFragment.newInstance(section));
    ft.commit();
}

@Override
public void onAttachFragment(Fragment fragment) {
    mFragments.add(new WeakReference<Fragment>(fragment));
}

private void recycleFragments() {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

    for (WeakReference<Fragment> ref : mFragments) {
        Fragment fragment = ref.get();
        if (fragment != null) {
            ft.remove(fragment);
        }
    }

    ft.commit();
}

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

...