Жизненный цикл фрагмента-какой метод вызывается при show / hide?
Я использую следующий метод для переключения между фрагментами (в моем NavigationDrawer) показывая / скрывая их.
protected void showFragment(int container, Fragment fragment, String tag, String lastTag, boolean addToBackStack ) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
if ( lastTag != null && !lastTag.equals("")) {
Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
if ( lastFragment != null ) {
transaction.hide( lastFragment );
}
}
if ( fragment.isAdded() ) {
transaction.show( fragment );
}
else {
transaction.add( container, fragment, tag );
}
if ( addToBackStack ) {
transaction.addToBackStack( tag );
}
transaction.commit();
// set the active tag
activeFragTag = tag;
}
что мне непонятно, это какой метод жизненного цикла фрагментов вызывается, когда я показываю или скрываю его? (поскольку нет такого метода, как onShow() или onHide (), я не совсем уверен, что использовать). Я хочу выполнить определенные действия при показе и скрытии определенного фрагмента.
8 ответов:
подобно жизненному циклу активности, Android вызывает onStart () когда фрагмент становится видимым.
onStop()
обычно вызывается, когда фрагмент становится невидимым, но он также может называться позднее.в зависимости от вашего макета Android можно назвать
onStart()
даже, когда ваш фрагмент еще не виден, но он принадлежит видимому родительскому контейнеру. Например, это справедливо дляandroid.support.v4.view.ViewPager
который требует от вас переопределитьFragment.setUserVisibleHint()
метод. В любом случае, если вам нужно зарегистрировать/отменить регистрацию BroadcastReceivers или других слушателей, вы можете смело использоватьonStart()
иonStop()
методы, потому что они будут вызываться всегда.Примечание: некоторые контейнеры фрагментов могут сохранять невидимые фрагменты запущенными. Чтобы справиться с этой ситуацией, вы можете переопределить
Fragment.onHiddenChanged(boolean hidden)
. Согласно документация, фрагмент должен быть как начато и видно (не скрыто), чтобы быть видимым для пользователь.обновление: если вы используете
android.support.v4.widget.DrawerLayout
после этого часть под ящиком остается начатой и видимой даже когда ящик открыт. В этом случае вам нужно использоватьDrawerLayout.setDrawerListener()
и слушатьonDrawerClosed()
иonDrawerOpened()
обратные вызовы.
Я @переопределить этот метод и решить мою проблему:
@Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); if (hidden) { //do when hidden } else { //do when show } }
off-course вы можете @ переопределить следующий метод, чтобы сделать это:
@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { // Do your Work } else { // Do your Work } }
попробуйте этот код:
@Override public void setUserVisibleHint(boolean visible) { super.setUserVisibleHint(visible); if (visible && isResumed()) { onResume(); } } @Override public void onResume() { super.onResume(); if (!getUserVisibleHint()) { return; } //Add your code this section }
просто попробуйте это в ваш setUserVisibleHint ()
@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if(isVisibleToUser && getView() != null){ isActive = true; init(); }else if(isVisibleToUser && getView() == null){ isActive = false; }else{ isActive = true; } }
и создать этот код onCreateView():
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if(!isActive){ init(); } }
setUserVisibleHint
передonCreateView
. и вы не можете обновить любой вид внутри setUserVisibleHint я используюpublic void setMenuVisibility(final boolean visible)
на visibility и onHiddenChanged () не вызывали в первый раз. он вызывает, когда скрытое состояние изменяется. потому что
fragment is visible by default
. Для того, чтобы достичь этого метода в первый раз, вы должны вызватьmFragmentTransaction.hide(oldFragment)
тогда он будет работатьПримечание
если вы хотите использовать setUserVisible подсказку и обновить представление использовать этот метод
другой способ вызова метода фрагмента, когда фрагмент виден, и вы используете viewpager в действии.
//прежде всего вы создаете интерфейс
public interface ShowFragmentVisible{ public void showFragment();}
//после этого этот интерфейс реализовать внутри фрагмента, как это
public class MyFragment extends Fragment implements ShowFragmentVisible { @Override public void showFragment() { }
/ / теперь идет ваша деятельность затем создать объект интерфейса и вызвать внутри, когда addOnViewpagerListener
ShowFragmentVisible showFragmentVisible; @Override public void onAttachFragment(Fragment fragment) { super.onAttachFragment(fragment); if (fragment instanceof ShowFragmentVisible) { showFragmentVisible = (ShowFragmentVisible) fragment; } } //your viewpager method viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (position==0){ showFragmentVisible.showFragment(); } } @Override public void onPageScrollStateChanged(int state) { } }); this is another alternative,but its work for me successfully
конечно, вы можете переопределить
setUserVisibleHint
илиsetMenuVisibility
но если вам нужно получить доступ кContext
илиActivity
, они будут null там! Есть еще один способonStart
который всегда имеет контекст, доступный под рукой, но он будет вызываться только один раз при создании фрагмента, и если вы начнете перемещаться между своими фрагментами на пейджере, вы увидите, что он не будет вызываться во втором представлении и после этого.так... что теперь делать?
обходной путь довольно прост, используйте
onStart
для первого посещения иsetMenuVisibility
на более поздние. Ваш код, вероятно, будет выглядеть следующим образом:класс фрагмент:
public class MyFragmentClass{ private boolean isCurrentVisible = false; ... @Override public void onStart() { super.onStart(); if (isCurrentVisible) doSth(); } @Override public void setMenuVisibility(boolean menuVisible){ super.setMenuVisibility(menuVisible); this.isCurrentVisible = menuVisible; if(menuVisible && getContext() != null) doSth(); }
таким образом
Context
всегда будет доступенdoSth()
метод.