Так что в основном то, над чем я работаю, очень похоже на приложение Instagram, где есть несколько вкладок, и пользователи могут переключаться на любую вкладку без каких-либо задержек, независимо от того, что происходит, например, обновление, перезагрузка и т. д. Он также использует кнопку «Назад», чтобы вернуться к предыдущей сохраненной вкладке.
Для этого я использовал FragmentManager
с FragmentTransaction
для отображения и скрытия каждого фрагмента, представляющего каждую вкладку. Я не использовал replace
или attach
/ detach
, потому что они разрушают иерархию представлений предыдущей вкладки.
Моя реализация работает довольно хорошо, за исключением того, что показ и скрытие фрагментов не фиксируются (я очень сомневаюсь, что это правильное слово, но пока я так понял поток.) или не происходят немедленно, когда SwipeRefreshLayout
обновление фрагмента (который должен быть скрыт), который был добавлен в FragmentManager
позже, чем отображаемый.
Моя реализация следует правилам, подобным этим. Допустим, у нас есть 4 вкладки, и моя MainActivity показывает первую вкладку, скажем, FirstFragment, а пользователь выбирает вторую вкладку, SecondFragment. Поскольку SecondFragment никогда раньше не добавлялся, я добавляю его в FragmentManager
с помощью FragmentTransaction.add
и скрываю FirstFragment с помощью FragmentTransaction.hide
. Если пользователь снова выбирает первую вкладку, поскольку FirstFragment ранее был добавлен в FragmentManager
, он не добавляется, а только показывает FirstFragment и просто скрывает SecondFragment. И выбор между этими двумя вкладками работает гладко.
Но когда пользователь "обновляет" SwipeRefreshLayout
SecondFragment и выбирает первую вкладку, FragmentTransaction
ожидает завершения обновления SecondFragment и фиксирует(?) фактическую транзакцию. Странно то, что транзакция немедленно фиксируется наоборот, от обновления FirstFragment до SecondFragment.
Поскольку это происходит в порядке добавления к FragmentManager
, я сомневаюсь, что порядок добавления как-то влияет на возврат фрагментов в исходное состояние, и может существовать что-то вроде приоритета потока пользовательского интерфейса, так что это заставляет транзакцию фрагмента выполняться после перехода пользовательского интерфейса добавленного позже фрагмента. заканчивается. Но у меня просто недостаточно подсказок, чтобы решить проблему. Я пробовал прикреплять/отсоединять и возвращать в исходное положение на FragmentTransaction
, но не смог решить проблему. Я пробовал и FragmentTransaction.commit
, и FragmentTransaction.commitAllowingStateLoss
, но ни один из них не решил проблему.
Это мой пример кода MainActivity.
private ArrayList<Integer> mFragmentsStack; // This is simple psuedo-stack which only stores
// the order of fragments stack to collaborate
// when back button is pressed.
private ArrayList<Fragment> mFragmentsList;
@Override
protected void onCreate() {
mFragmentsStack = new ArrayList<>();
mFragmentsList = new ArrayList<>();
mFragmentsList.add(FirstFragment.newInstance());
mFragmentsList.add(SecondFragment.newInstance());
mFragmentsList.add(ThirdFragment.newInstance());
mFragmentsList.add(FourthFragment.newInstance());
mMainTab = (MainTab) findViewById(R.id.main_tab);
mMainTab.setOnMainTabClickListener(this);
int currentTab = DEFAULT_TAB;
mFragmentsStack.add(currentTab);
getSupportFragmentManager().beginTransaction().add(R.id.main_frame_layout,
mFragmentsList.get(currentTab), String.valueOf(currentTab)).commit();
mMainTab.setCurrentTab(currentTab);
}
// This is custom interface.
@Override
public void onTabClick(int oldPosition, int newPosition) {
if (oldPosition != newPosition) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
// First hide the old tab.
fragmentTransaction.hide(mFragmentsList.get(oldPosition));
// Recalculate the fragment stack.
if (mFragmentsStack.contains(newPosition)) {
mFragmentsStack.remove((Integer) newPosition);
}
mFragmentsStack.add(newPosition);
// Add new fragment if it's not added before, or show new fragment which was already hidden.
Fragment fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(newPosition));
if (fragment != null) {
fragmentTransaction.show(fragment);
} else {
fragmentTransaction.add(R.id.main_frame_layout, mFragmentsList.get(newPosition),
String.valueOf(newPosition));
}
// Commit the transaction.
fragmentTransaction.commitAllowingStateLoss();
}
}
// It mimics the tab behavior of Instagram Android application.
@Override
public void onBackPressed() {
// If there's only one fragment on stack, super.onBackPressed.
// If it's not, then hide the current fragment and show the previous fragment.
int lastIndexOfFragmentsStack = mFragmentsStack.size() - 1;
if (lastIndexOfFragmentsStack - 1 >= 0) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.hide(mFragmentsList.get(mFragmentsStack.get(lastIndexOfFragmentsStack)));
fragmentTransaction.show(mFragmentsList.get(mFragmentsStack.get(lastIndexOfFragmentsStack - 1)));
fragmentTransaction.commitAllowingStateLoss();
mMainTab.setCurrentTab(mFragmentsStack.get(lastIndexOfFragmentsStack - 1));
mFragmentsStack.remove(lastIndexOfFragmentsStack);
} else {
super.onBackPressed();
}
}
executePendingTransactions()
после операторов фиксации, но это не работает. Мне интересно, правильно ли это место, потому что то, что говорится в документе, похоже, является ответом на мою ситуацию. - person Lee Han Kyeol   schedule 20.05.2015