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

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