Фрагмент onResume () & onPause () не вызывается в backstack
у меня есть несколько фрагментов внутри активности. При нажатии кнопки я запускаю новый фрагмент, добавляя его в backstack. Я, естественно, ожидал onPause()
метод текущего фрагмента и onResume()
нового фрагмента для вызова. Но этого не происходит.
LoginFragment.java
public class LoginFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
final FragmentManager mFragmentmanager = getFragmentManager();
Button btnHome = (Button)view.findViewById(R.id.home_btn);
btnHome.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
HomeFragment fragment = new HomeFragment();
FragmentTransaction ft2 = mFragmentmanager.beginTransaction();
ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left
, R.anim.slide_left, R.anim.slide_out_right);
ft2.replace(R.id.middle_fragment, fragment);
ft2.addToBackStack("");
ft2.commit();
}
});
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of LoginFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of loginFragment");
super.onPause();
}
}
HomeFragment.java
public class HomeFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of HomeFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of HomeFragment");
super.onPause();
}
}
то, что я ожидал, было,
- при нажатии кнопки LoginFragment заменяется с
HomeFragment,
onPause()
of LoginFragment иonResume()
of HomeFragment вызывается - когда назад нажата,HomeFragment выскочил и LoginFragment is
видел, и
onPause()
of HomeFragment иonResume()
of LoginFragment вызывается.
что я получаю это,
- при нажатии кнопки , HomeFragment правильно заменить LoginFragment, onResume () of HomeFragment называется, но onPause() из LoginFragment никогда не вызывается.
- при нажатии назад,HomeFragment правильно появляются, чтобы выявить LoginFragment, onPause () of HomeFragment получает вызов, но onResume() из LoginFragment никогда не вызывается.
Is это нормальное поведение? Почему это onResume()
of LoginFragment не вызывается, когда я нажмите кнопку Назад.
15 ответов
фрагментов onResume()
или onPause()
будет вызываться только тогда, когда действия onResume()
или onPause()
называется.
Они тесно связаны с Activity
.
читать обработка раздела жизненного цикла фрагмента этой статьи.
- так как вы использовали
ft2.replace()
,FragmentTransaction.remove()
метод называется иLoginfragment
будут удалены. См.этой. Так чтоonStop()
ofLoginFragment
будет вызываться вместоonPause()
. (Как новый фрагмент полностью заменяет старый). - но так как у вас также
используется
ft2.addtobackstack()
, состояниеLoginfragment
будет сохранено в виде пакета и при нажатии кнопки "назад" изHomeFragment
,onViewStateRestored()
будет называться с последующимonStart()
ofLoginFragment
. Так что в конце концовonResume()
не назовешь.
Если вы действительно хотите заменить фрагмент В фрагмент вы должны использовать Вложенные Фрагменты.
в вашем коде вы должны заменить
final FragmentManager mFragmentmanager = getFragmentManager();
С
final FragmentManager mFragmentmanager = getChildFragmentManager();
вот моя более надежная версия ответа гора (с использованием фрагментов.размер () ненадежен из-за того, что размер не уменьшается после того, как фрагмент выскочил)
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getFragmentManager() != null) {
Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager());
if (topFrag != null) {
if (topFrag instanceof YourFragment) {
//This fragment is being shown.
} else {
//Navigating away from this fragment.
}
}
}
}
});
и метод "getCurrentTopFragment":
public static Fragment getCurrentTopFragment(FragmentManager fm) {
int stackCount = fm.getBackStackEntryCount();
if (stackCount > 0) {
FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1);
return fm.findFragmentByTag(backEntry.getName());
} else {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size()>0) {
for (Fragment f: fragments) {
if (f != null && !f.isHidden()) {
return f;
}
}
}
}
return null;
}
у меня есть код очень похож на ваш, и если он работает onPause () и onResume (). При изменении фрагмента эти функции активируются соответственно.
фрагмент кода:
@Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL);
Log.e("Frontales","resume");
}
@Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
Log.e("Frontales","Pause");
}
Log при изменении фрагмента:
05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause
фрагмент onCreateView:
View rootView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_proximidad, container, false);
ButterKnife.bind(this,rootView);
inflar();
setTextos();
return rootView;
}
действие, когда я пульсирую назад (в активности, где я загружаю фрагмент):
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
простые Не могу добавить фрагмент к фрагменту. Это должно произойти во фрагментарной активности. Я предполагаю, что вы создаете LoginFragment в FragmentActivity, поэтому для того, чтобы получить эту работу, вам нужно добавить HomeFragment через FragmentActivity, когда логин закрывается.
общий момент заключается в том, что вам нужен класс FragmentActivity, из которого вы добавляете каждый фрагмент в FragmentManager. Это не возможно чтобы сделать это внутри фрагмента класс.
Если вы добавляете фрагмент в XML, вы не можете динамически менять их местами. Происходит то, что они чрезмерно, поэтому они не срабатывают, как можно было бы ожидать. Проблема задокументирована в этом вопросе. замена FragmenManager делает наложение
превратите middle_fragment в FrameLayout и загрузите его, как показано ниже, и ваши события будут срабатывать.
getFragmentManager().beginTransation().
add(R.id.middle_fragment, new MiddleFragment()).commit();
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
List<Fragment> fragments = getFragmentManager().getFragments();
if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){
//todo if fragment visible
} else {
//todo if fragment invisible
}
}
});
но будьте осторожны, если видно более одного фрагмента
что я делаю в фрагменте ребенка:
@Override
public void onDetach() {
super.onDetach();
ParentFragment pf = (ParentFragment) this.getParentFragment();
pf.onResume();
}
а затем переопределить onResume на ParentFragment
фрагмент всегда должен быть встроен в действие, и жизненный цикл фрагмента напрямую зависит от жизненного цикла действия хоста. Например, когда действие приостановлено, все фрагменты в нем, и когда действие разрушено, все фрагменты
Вы можете попробовать это,
Шаг 1: переопределите метод Tabselected в вашей активности
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
try {
if(MyEventsFragment!=null && tab.getPosition()==3)
{
MyEvents.fragmentChanged();
}
}
catch (Exception e)
{
}
mViewPager.setCurrentItem(tab.getPosition());
}
Шаг 2: используя статический метод, сделайте то, что вы хотите в своем фрагменте,
public static void fragmentChanged()
{
Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show();
}
onPause()
метод работает в классе activity, который вы можете использовать:
public void onDestroyView(){
super.onDestroyView
}
для той же цели..
выполните следующие действия, и вы получите необходимый ответ
1-для обоих фрагментов создайте новый абстрактный Родительский фрагмент.
2-Добавьте пользовательский абстрактный метод, который должен быть реализован ими обоими.
3-вызовите его из текущего экземпляра перед заменой на второй.
на основе ответа @Gor Я написал подобное в Котлине. Поместите этот код в onCreate()
действия. Он работает для одного видимого фрагмента. Если у вас есть ViewPager
С фрагментами, он будет вызывать ViewPager
фрагмент, а не предыдущий.
supportFragmentManager.addOnBackStackChangedListener {
supportFragmentManager.fragments.lastOrNull()?.onResume()
}
после чтения https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 я понял, что во многих ситуациях было бы лучше прикреплять новые фрагменты с помощью replace
, а не add
. Так что потребность в onResume
в некоторых случаях исчезнет.
при создании транзакции фрагмента обязательно добавьте следующий код.
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
также убедитесь, что после добавления транзакции в backstack