Intereting Posts
Обнаружено устройство Android, подключенное к ПК Java – лучшая практика для геттеров, одного геттера или нескольких для разных переменных? В чем разница между линейным и относительным расположением? MPAndroidChart – Как показать значения y, когда ваше значение равно нулю? Phonegap получает значения localstorage из Java-кода? Установить <String> в android sharedpreferences не сохраняет силу Ошибка обратного вызова для передачи: результат = ОТМЕНА forIntent {act = com.google.android.c2dm.intent.RECEIVE pkg = com.flagg327.guicomaipu (есть дополнительные функции)} Может ли проект библиотеки Android иметь собственную базу данных SQLite? Радиальный градиент Android Состояние сохранения Android при изменении ориентации Почему эти разрешения отказываются? Создание службы на Android Использование метода updateAppWidgetOptions для AppWidgetManager для хранения параметров настройки виджета Android MVP – Как общаться между презентатором активности и презентатором фрагментов Статические методы или Синглтон, какой из них выбрать?

Фрагменты все еще добавляются в backstack без вызова addToBackStack, почему?

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

Я называю это FragmentChanger

У этого есть fragmentContainer , который является ViewGroup , который содержит все фрагменты, которые я хотел бы показать.

Я сделал свою собственную replace(Fragment fragmentToChange, boolean needSaveToBackStack)

Функция, которая:

  • Удаление старого фрагмента фрагментаContainer
  • Добавление нового фрагмента к фрагментуContainer
  • При необходимости сохраняет значение backStack, а needSaveToBackStacktrue или false .

Ошибка заключается в следующем:

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

Но когда я хотел бы заменить фрагмент без сохранения на backStack, в моем коде есть что-то не так, потому что, когда я отступаю, я вижу на экране фрагмент, который я НЕ добавил в backStack , и ТАКЖЕ, я могу видеть другое Ранее был добавлен фрагмент в одно и то же время!

Таким образом, я могу видеть 2 фрагмента в одно и то же время, например:

Введите описание изображения здесь

Это мой код:

 //It is my helper class to handle replacing fragments. public class FragmentChanger { // fragmentTransaction FragmentTransaction fragmentTransaction; // the container for fragments ViewGroup fragmentContainer; // activity ofc Activity act; // Ctr: adding a default fragment to be the first so we can see it at app // start public FragmentChanger(Activity act, ViewGroup container, Fragment startingFragment) { this.act = act; this.fragmentContainer = container; fragmentTransaction = act.getFragmentManager().beginTransaction(); fragmentTransaction.add(container.getId(), startingFragment, startingFragment.getClass().getSimpleName()); fragmentTransaction.addToBackStack(startingFragment.getClass().getSimpleName()); fragmentTransaction.commit(); } // Replacing a fragment with an other one public void replace(Fragment fragmentToChange, boolean needSaveToBackStack) { fragmentTransaction = act.getFragmentManager().beginTransaction(); // replacing old fragment to the new one! fragmentTransaction.replace(fragmentContainer.getId(), fragmentToChange, fragmentToChange.getClass().getSimpleName()); // Some null checking, and if the new fragment is NOT equals the current // fragment if (getCurrentFragment() != null && getCurrentFragment() != fragmentToChange) { /*** Important** because something here is wrong ***/ // only addToBackStack when i want it, when needSaveToBackStack = // true! if (needSaveToBackStack) { fragmentTransaction.addToBackStack(fragmentToChange.getClass().getSimpleName()); } } // commiting changes fragmentTransaction.commit(); } // getting current Fragment private Fragment getCurrentFragment() { try { FragmentManager fragmentManager = act.getFragmentManager(); String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); Fragment currentFragment = act.getFragmentManager().findFragmentByTag(fragmentTag); return currentFragment; } catch (Exception ex) { ex.printStackTrace(); } return null; } // Logging the back stack public void logBackStack() { Log("Logging back stack:", "============="); FragmentManager fragmentManager = act.getFragmentManager(); int stackSize = fragmentManager.getBackStackEntryCount(); Log("Fragments count on the stack: ", stackSize + ""); for (int i = 0; i < stackSize; i++) { String fragmentTag = fragmentManager.getBackStackEntryAt(i).getName(); Log("Fragment on the stack: ", fragmentTag); } } private void Log(String str, String msg) { Log.i(str, msg); } } 

И это моя MainActivity, где я проверяю класс вспомогательного фрагмента:

 public class MainActivity extends Activity implements OnClickListener { // My 3 Fragment Classes, could be N other type, // in this example I only got 3 FragmentA fragmentA; FragmentB fragmentB; FragmentC fragmentC; // Button to add the fragments manually Button addA, addB, addC; // This is my activity's container, its a simple viewGroup // could be anything that can hold fragments ViewGroup fragmentContainer; // This is my fragment changer helper class that need some revision by you // guys FragmentChanger fragmentChanger; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //defining my adding buttons addA = (Button)findViewById(R.id.addAbtn); addB = (Button)findViewById(R.id.addBbtn); addC = (Button)findViewById(R.id.addCbtn); //setting onclicklistenrs addA.setOnClickListener(this); addB.setOnClickListener(this); addC.setOnClickListener(this); // defining my main container, this will holds fragments fragmentContainer = (ViewGroup) findViewById(R.id.fragmentContainer); // defining my fragments, each of them got an Activity (this), a // Container (mainContainer), and a Layout ofc. fragmentA = new FragmentA(this, fragmentContainer, R.layout.fragment_a_layout); fragmentB = new FragmentB(this, fragmentContainer, R.layout.fragment_b_layout); fragmentC = new FragmentC(this, fragmentContainer, R.layout.fragment_c_layout); // defining my fragment changer with an activity(this), a // container(mainContent) and a starting fragment to show! fragmentChanger = new FragmentChanger(this, fragmentContainer, fragmentA); } @Override public void onClick(View view) { if (view.equals(addA)) { //When adding fragmentA, i always want to save it to backstack fragmentChanger.replace(fragmentA, true); } else if (view.equals(addB)) { //I dont want to save to back stack when adding B //So if i press back button, i dont want to see fragmentB ever again. //(But i do see, this is the error.) fragmentChanger.replace(fragmentB, false); } else if (view.equals(addC)) { //When adding fragmentC, i always want to save it to backstack fragmentChanger.replace(fragmentC, true); } //After any modification on fragments, i log the backstack fragmentChanger.logBackStack(); } 

}

Ps: Я могу ясно видеть, что фрагментB никогда не находится на backStack, если я регистрирую стек каждый раз, когда я заменяю фрагмент моим вспомогательным классом. Тогда почему это появляется, если я нажимаю кнопку?

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

Solutions Collecting From Web of "Фрагменты все еще добавляются в backstack без вызова addToBackStack, почему?"

Итак, вот что я нашел не так с вашим кодом:

1) Вы смешиваете теги Fragment и BackStackEntry .

 String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); 

Итак, здесь вы получаете тег BackStackEntry (не Fragment ), который вы добавляете или нет в fragmentTransaction.addToBackStack() . Следовательно, вы получаете неправильное состояние и используете его как текущий фрагмент.

2) Как правило, не рекомендуется хранить и повторно использовать фрагменты, как в ваших классах: FragmentA fragmentA; , Это может привести к проблемам с состоянием и инфляцией, лучше создавать их при каждой транзакции, если вы не хотите решать дополнительные головоломки.

Попробуйте заменить фрагмент с помощью метода FragmentTransacion.replace, как показано в ссылке здесь.

И вы также можете ссылаться на этот пример. Это отлично работает для меня.

Во-первых, в конструкторе класса FragmentChanger вы добавляете все фрагменты в свою заднюю часть. Поскольку вы добавляете их в порядок, они добавляются как A, B, а затем C. После добавления их в стопку в этом порядке вы делаете больше транзакций поверх него. Инициализируя их, не добавляйте их в заднюю часть. Добавляйте / удаляйте их только при нажатии кнопки.

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

Если вы хотите добавить фрагмент в backStack, тогда сделайте .replace(params ).addToBackStack(Tag)

Если вы не хотите добавлять определенный фрагмент, просто полностью пропустите addToBackStack(Tag) .

Также ваш getCurrentFragment() можно изменить на

Fragment currentFrag=getFragmentManager().findFragmentById(R.id.fragment_container);

Прочтите этот ОТВЕТ здесь для лучшего объяснения, а также этот ОТВЕТ