Жизненный цикл фрагмента-какой метод вызывается при 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 calls 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() обратные вызовы.


I @переопределить этот метод и решить мою проблему:

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
        //do when hidden
    } else {
       //do when show
    }
}

выкл-конечно можно @Overriede следующий метод, чтобы сделать так:

@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)

на видимость и onHiddenChanged () не вызывали в первый раз. он вызывает при изменении скрытого состояния. потому что fragment is visible by default. Чтобы достичь этого метода в первый раз, вам нужно вызвать mFragmentTransaction.hide(oldFragment) тогда он будет работать

Примечание

если вы хотите использовать подсказку setUserVisible и представление обновления использовать этот метод


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

/ / прежде всего вы создаете интерфейс

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() метод.