FragmentManager.popBackStack () не просто загружает предыдущий фрагмент - PullRequest
6 голосов
/ 01 апреля 2012

У меня есть основная TabActivity , которая имеет две вкладки, A и B (на данный момент).Tab A загружает FragmentActivity (приведенный ниже код), который просто содержит FrameLayout, поэтому я могу загрузить в него свои фрагменты для этой конкретной вкладки.

Первый фрагмент имеет несколько TextViews и один ListView .Данные извлекаются из веб-службы.Когда я нажимаю на элемент ListView, я загружаю детали этого элемента в другом фрагменте (это также происходит из веб-службы) и заменяю текущий фрагмент (с ListView и другими элементами управления) другим фрагментом детали.

Для достижениядля этого я использую библиотеку android-support-v4.jar , чтобы использовать фрагменты так, как они предпочитали.

XML-код FragmentActivity вкладки A:

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <FrameLayout
            android:id="@+id/updates_frame"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="@drawable/background"/>
    </LinearLayout>

FragmentActivity вкладки AКод Java:

public class UpdatesFragmentActivity extends FragmentActivity implements
    IUpdateNotifier {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.updates);

        //Load Initial Fragment into FrameLayout
        //I am adding this Fragment to BackStack
        Fragment newFragment = new UpdatesFragment();
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.addToBackStack(null);
        ft.add(R.id.updates_frame, newFragment);
        ft.commit();
    }

    //This is an Interface method which I call with the clicked "FEED" object to load its detail in another Fragment
    @Override
    public void onFeedSelected(Feed feed) {
        // Instantiate a new fragment.
        Fragment newFragment = new FeedDetailFragment(feed);

        // Add the fragment to the activity, pushing this transaction
        // on to the back stack.
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.updates_frame, newFragment);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.addToBackStack(null);
        ft.commit();
    }

    //This is another Interface Method which I call when the user presses "BACK".
    //I am trying to load the previously loaded Fragment, which I added to BackStack.
    //But this causes reconstruction of the previously loaded fragment. LIST in this case
    //which call the web service. I DONT WANT TO CALL SERVICE AGAIN.
    @Override
    public void onBackPressed() {
        FragmentManager fm = getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            fm.popBackStack();
        }
    }
}

Я создал интерфейс IUpdateNotifier , который содержит два метода:

public void onFeedSelected(Feed feed);
public void onBackPressed();

Parent UpdatesFragmentActivity реализует эти методы,Я вызываю эти методы от дочерних фрагментов после следующих действий.

  1. Я вызываю onFeedSelected (Feed feed) из фрагмента, который имеет ListView .Я отправляю выбранный элемент канала в родительский FragmentActivity, поэтому он загружает другой фрагмент, который будет содержать эту информацию канала.
  2. Я вызываю onBackPressed () из второго фрагмента сведений канала, когда пользователь нажимаеткнопка, которая должна вернуть первый фрагмент, который содержал ListView с другими элементами управления.Как вы можете видеть, я пытаюсь вызвать метод FragmentManager popBackStack () , чтобы вернуть этот первый фрагмент ...

Но первый фрагмент обновляется и загружает все данные извеб-сервис.

На самом деле я не могу получить и сохранить данные только один раз, а обновления происходят через определенные промежутки времени.Пользователь может обновить список, когда он хочет.Первоначально список загружает 10 лучших элементов из службы, а затем пользователь может нажать кнопку «Еще» в конце списка, если он хочет загрузить больше элементов.

Он загрузит следующие 10 элементов и так далее.Но я думаю, что могу сохранить полученный ArrayList в некоторой переменной в UpdatesFragmentActivity , а затем просто переназначить этот ArrayList адаптеру списка вместо загрузки данных из службы, но я не знаю, как заставить Fragment непозвоните в сервис снова.

Я хочу, чтобы он вел себя как при нажатии на вкладку 2, а затем снова на вкладку 1.Он просто показывает загруженные данные, как если бы они были скрыты, и не вызывает службу.

Как этого добиться?

Ответы [ 2 ]

4 голосов
/ 01 апреля 2012

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

Есть несколько простых исправлений, но яне знаю, что будет работать лучше, так как вы дали небольшую информацию о проблеме.

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

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

Существует руководство по этому подходу, котороеможно найти здесь http://android.arnodenhond.com/tutorials/alarm-notification.

Наконец;вам не нужно вставлять задний стек, чтобы обойти эту проблему, хотя вы, возможно, делаете это по совершенно другим причинам, но трудно сказать без дополнительной информации.

2 голосов
/ 27 февраля 2013

Ваш вопрос недостаточно ясен, задавайте более простые и точные вопросы ... И, как вы сказали выше

popBackStack не загружает последний фрагмент, его обычно используют для извлечения всего стека:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 

перед загрузкой другого фрагмента

beginTransaction()
replace() Or add()
commit()

Это все, о чем я могу думать с этим вопросом

Удачи

...