Как воссоздать представление списка бывшего ListFragment после нажатия кнопки возврата

У меня есть ListFragment со списком в нем, который содержит структуру навигации. При выборе элемента списка должен отображаться следующий этап иерархии навигации. И так далее.

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

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

Я подумал, что было бы неплохо использовать onSaveInstanceState. Но onSaveInstanceState не вызывается, когда транзакция завершается. Я проверил это, поместив Log.d ("..", "...) в метод. Он не вызывается. (Я выяснил, что onSaveInstanceState вызывается при повороте из книжной в альбомную ориентацию). вид и наоборот. Но это не помогает моей проблеме).

Итак, как было бы лучше всего сохранить элементы представления списка и вернуть его, чтобы воссоздать представление списка после использования кнопки «Назад» и создания бывшего фрагмента? Все элементы представляют собой строки, которые хранятся в ArrayList, привязанном к ListAdapter.


Вот мой код. Я реализовал интерфейс, щелчок по элементу в списке вызывает метод родительского действия. В этом методе я сначала вызываю метод для заполнения уже существующего ArrayList (navigationsItems) новыми элементами, которые являются содержимым следующего этапа навигации:

Код моего ArrayAdapter:

arrayAdapterFuerNaviList = new ArrayAdapter<String>(
        BRC_BoardOverviewActivity.this,
        android.R.layout.simple_list_item_1, 
                    navigationsItems);

В этом методе я сначала вызываю метод для заполнения ArrayList (navigationsItems) элементами следующего этапа навигации:

// load new itemlist to navigation-
public void inhaltAktuelleNaviListeInArrayLaden() {

    navigationsItems.clear();
    for (int i = 0; i < prefs.getInt("aktuelleNaviListe_size", 0); i++) {
        (...)
        navigationsItems.add(titel);
    }
}

Затем я вызываю метод, с помощью которого загружаю новый ListFragment и привязываю к нему новый ArrayAdapter:

// push navifragment to BackStack and create a new instance of it
public void naviFragmenteNeuLaden() {

            // get a reference to the actual ListFragment
    Fragment removefragment = frgm.findFragmentById(R.id.navi_container);

    // initialize ne ListFragment
    BRC_NavigationsFragment navifragment = (BRC_NavigationsFragment) frgm
            .findFragmentById(R.id.navi_container);

    // remove the old and bind the new ListFragment from/to the container ...
    FragmentTransaction frgmta = frgm.beginTransaction();
    frgmta.remove(removefragment);
    frgmta.add(R.id.navi_container, navifragment);

    // ... push the old ListFragment on the BackStack and commit ...
    frgmta.addToBackStack(null);
    frgmta.commit();
    frgm.executePendingTransactions();

    // ... bind the updated ArrayAdapter to the new ListFragment ...
    try {
        navifragment.setListAdapter(arrayAdapterFuerNaviList);
    } catch (Exception e) {
        // TODO 
        e.printStackTrace();
    }

    // ... and notify 
    try {
        arrayAdapterFuerNaviList.notifyDataSetChanged();
    } catch (Exception e) {
        // TODO 
        e.printStackTrace();
    }
}

Как уже упоминалось, прямая навигация не проблема. Но когда я нажимаю кнопку возврата, например, на 2-м этапе навигации загружается бывший ListFragment (проверенный с помощью Log.d ("...". "...) - Сообщения в onCreatView () ListFragment), но прежнее представление списка, которое было в нем, не является т создан.


Сейчас я работаю над новым подходом. Когда вы щелкаете по элементу в списке, я записываю текущий список вместе со ссылкой на текущий ListFragment в векторный стек. Затем ловлю методом «onBackPressed ()» нажатие кнопки «назад». Итак, теперь, когда кнопка нажата, я вызываю уже упомянутые методы (см. Выше), записываю данные элемента из стека обратно в список, вызываю через сохраненную ссылку форму ListFragmt и привязываю к ней обновленный ArrayAdapter. На самом деле это работа. Я напишу результат такого подхода, когда закончу.


comment
Почему бы не сделать ListFragment для каждого из этих экранов?   -  person user    schedule 07.02.2013
comment
Как я уже упоминал, я создаю новый ListFragment с новым Listview, перемещаясь вперед. Пример a) Элемент 1 нажат. B) создание нового ListFragment; поместите старый ListFragment в backStack c) выбор нужных элементов для следующего этапа навигации d) привяжите новые элементы к новому ListFragment e) дальнейшая навигация завершена! До сих пор все работает нормально! Тогда проблема: пользователь находится на следующем этапе (см. От a) до e) выше) и f) нажимает кнопку возврата. g) Прежний ListFragment извлекается из backStack h) ListFragment создается i) но прежний ListView не создается (пустой ListFragment)   -  person KuJo    schedule 07.02.2013
comment
Опубликуйте код, который вы используете для заполнения этого ListFragment, а также то, как вы переходите к следующему фрагменту.   -  person user    schedule 07.02.2013
comment
Я добавил код. См. Выше.   -  person KuJo    schedule 07.02.2013
comment
Также я добавил объяснение нового подхода к решению моей проблемы.   -  person KuJo    schedule 07.02.2013
comment
Я думаю, вы усложняете ситуацию, используя один и тот же фрагмент. Взгляните на другой подход. gist.github.com/luksprog/4731357   -  person user    schedule 07.02.2013
comment
Спасибо за код на github. Но с этим у меня возникла новая проблема. Иерархия навигации не исправлена. Это зависит от структуры дискуссионного форума (доска, форум, подфорум и т. Д.) И его содержания (тем). Эта структура загружается в родительскую активность и зависит от прав пользователя в дискуссионном форуме (например, участник может видеть больше форумов, чем гости; таким образом изменяется и глубина навигации). Поэтому мне нужно создавать структуру навигации на лету. В вашем подходе у меня должны быть списки исправлений для нескольких этапов навигации, которых у меня нет.   -  person KuJo    schedule 07.02.2013


Ответы (1)


Я решил проблему.

Для различного содержимого навигации ListView я определил класс «Naviliste», в котором хранятся все элементы. Если кто-то нажимает на элемент, будет сгенерировано новое представление списка с соответствующим новым списком. Эти списки проиндексированы, поэтому каждому списку присваивается фиксированный идентификатор.

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

Если пользователь нажимает кнопку «Назад», чтобы вернуться на шаг назад, выполняется следующее:

Нажатие кнопки «Назад» улавливается методом onPressedBack (), размещенным в родительском действии. Через этот метод вызывается собственный метод. Это извлекает последний идентификатор, который был помещен в стек, а затем строит с ним в новом созданном фрагменте прежний список.

В то же время я буду бегать по счетчику, который считает, на какой глубине навигации я нахожусь. На каждом шаге навигации вперед он увеличивается на 1. А в обратном направлении просто уменьшается на 1. С помощью этого счетчика я могу запросить, находится ли пользователь в корневом каталоге навигации (counter = 0), и еще раз нажмите кнопку «Назад» чтобы выйти из текущего действия. Если это так, я вызываю finish (), и родительская операция с ее фрагментами закрывается. Вуаля!

Работает отлично. Потребовалось немного времени, чтобы это преодолеть. Но теперь я счастлив, что мое решение работает. :)

person KuJo    schedule 08.02.2013