Подтвердить что ты не робот

Фрагмент addToBackStack() и popBackStackImmediate() не работают

В настоящее время я создаю приложение для Android (14 <= SDK <= 21), используя один ActionBarActivity и более Fragments, например ListFragment и MapFragment, которые меняются в пределах одного FrameLayout.

ActionBarActivity автоматически заменяет/фиксирует фрагмент A. Затем, когда пользователь нажимает кнопку, хостинг Activity заменяет/фиксирует новый другой фрагмент B. Моя цель - позволить пользователю вернуться к фрагменту A, как только она нажимает кнопка назад.

Некорректный код.

MainActivity

public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener,
    StopItemFragment.OnFragmentInteractionListener {
...

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

        fragmentManager = getFragmentManager();
        fragmentManager.enableDebugLogging(true);
        ...
        if (fragmentManager.findFragmentById(R.id.content_frame) == null) {
            StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
            fragmentManager.beginTransaction()
                .replace(R.id.content_frame, list)
                .addToBackStack(null)
                .commit();
        }
        ...

        @Override
        public void onFragmentInteraction(String id) {
        selectItem(Integer.parseInt(id));
        }


       private void selectItem(int position) {
       StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
       ...
       fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment)
            .commit();

       ...
       }
}


Проблема

Даже если вызывается addToBackStack(), когда я нахожусь на фрагменте B, я не могу вернуться к фрагменту A. MainActivity напрямую закрыт. Тем не менее я пытался управлять задним стеклом сам по себе, не повезло. Я вижу, что фрагмент находится в стеке, но если я вызываю popBackStackImmediate(), фрагмент A выскочит и транзакция фрагмента не будет выполнена. (первая обратная печать ничего не происходит, вторая активность закрыта)

Я также прикрепляю logcat FragmentManager:
http://pastebin.com/hFLHprL8

4b9b3361

Ответ 1

Для тех, кто все еще ищет решение.

В основном классе Activity (который размещает фрагменты) просто переопределяет onBackPressed().

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

В фрагменте нет метода onBackPressed(), и этот метод предназначен только для Activity. Итак, когда мы нажимаем клавишу "назад", отображается поведение по умолчанию Activity, которое равно

вы либо перейдете к предыдущему действию (если есть), либо к приложению выйдет.

Теперь нам нужно переопределить этот метод, чтобы сообщить Activity, что, когда мы нажимаем клавишу "Назад", если есть какие-либо фрагменты в стеке, вытащите их (и это произойдет, когда addToBackStack() появится на картинке). В противном случае выполните поведение по умолчанию.

Ответ 2

Попробуйте это (Примечание добавить не заменить для фрагмента А и addToBackStack() для фрагмента B)

StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
        fragmentManager.beginTransaction()
            .add(R.id.content_frame, list)
            .commit();

и

StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
   ...
   fragmentManager.beginTransaction()
        .replace(R.id.content_frame, fragment)
        .addToBackStack("FragmentB")
        .commit();

Ответ 3

Мне пришлось называть beginTransaction() и commit() of FragmentManager вручную.
Решено путем переопределения onBackPressed():

@Override
public void onBackPressed() {
    ...
    if (fragmentManager.getBackStackEntryCount() > 1){
        fragmentManager.popBackStackImmediate();
        fragmentManager.beginTransaction().commit();
    } else {
        //handle finish
        finish(); // Closes app
    }
}

Ответ 4

Если вы боретесь с addToBackStack() и popBackStack(), просто используйте

FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`

В вашей деятельности В OnBackPressed() найдите мерцание по тегу, а затем сделайте свой материал

Fragment home = getSupportFragmentManager().findFragmentByTag("Home");

if (home instanceof HomeFragment && home.isVisible()) {
    // do you stuff
}

Для получения дополнительной информации https://github.com/DattaHujare/NavigationDrawer  Я никогда не использую addToBackStack() для обработки фрагмента.

Ответ 5

причина, по которой popBackStack() и popBackStackImmediatly() связаны с тем, что вы не добавили этот фрагмент (который вы хотите выложить) в backStack. Чтобы сделать это, вы должны сделать вызов addToBackStack() в момент совершения транзакции, чтобы добавить/заменить ваш фрагмент.

Ответ 6

Прежде всего, я хотел бы сказать большое спасибо за выделенный ответ [Ник] (Низкая репутация не может комментировать внизу), за то, что он помог мне узнать, действительно ли было то, что не упоминалось в Документации Android.

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

@Override
public boolean onSupportNavigateUp() {

    if (getSupportFragmentManager().popBackStackImmediate()){
        return true;
    }

    return super.onSupportNavigateUp();
}

Вышеупомянутый код на Java (снимок экрана)

Постскриптум Мой первый ответ нИКОГДА о stacksoverflow после более чем 5-летнего использования ^^