Жизненный цикл фрагментов - какой метод вызывается 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() im, не совсем уверен что использовать). Я хочу выполнить определенные действия при показе и скрытии определенного фрагмента.

Ответ 1

Подобно жизненному циклу активности, 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().

Ответ 2

I @Переопределите этот метод и устраните мою проблему:

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

Ответ 3

вне курса вы можете @Overriede использовать следующий метод:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            // Do your Work
        } else {
            // Do your Work
        }
    }

Ответ 4

Попробуйте этот код:

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

Ответ 5

Просто попробуйте это в 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();
  }
}

Ответ 6

setUserVisibleHint вызов до onCreateView. и вы не можете обновить любой вид внутри setUserVisibleHint Я использую

public void setMenuVisibility(final boolean visible)

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

Примечание

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

Ответ 7

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

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

public interface ShowFragmentVisible{
      public void showFragment();}

//После этого этот интерфейс реализует внутри Fragment, подобный этому

      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

Ответ 8

Конечно, вы можете переопределить setUserVisibleHint или setMenuVisibility но если вам нужен доступ к Context или Activity, они там будут нулевыми! Существует другой метод 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().

Ответ 9

Вы можете использовать onCreateView (или onActivityCreated) и onHiddenChanged. Используйте "onCreateView" для первого показа и "onHiddenChanged" для последующего показа. setMenuVisibility не вызывается при управлении транзакциями.

@Override
public View OnCreateView() {
   // fragment will show first
}

@Override
public void onHiddenChanged(boolean hidden) {
    if (!hidden) {
        // fragment will show 
    }
    else {
        // fragment will hide
    }
}

Ответ 10

Поведение пейджера в представлении фрагментов отличается от обычного контейнера фрагментов.

Попробуйте этот код:

    boolean mIsVisibleToUser;

    /**
     * is visible to user
     */
    public void show() {
        //do when show
    }

    /**
     * is invisible to user
     */
    public void hide() {
        //do when gone
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!mIsVisibleToUser && getUserVisibleHint()) {
            mIsVisibleToUser = true;
            show();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mIsVisibleToUser && getUserVisibleHint()) {
            mIsVisibleToUser = false;
            hide();
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isResumed()) {
            if (mIsVisibleToUser != isVisibleToUser) {
                mIsVisibleToUser = isVisibleToUser;
                if (isVisibleToUser) show();
                else hide();
            }
        }
    }

    public boolean isVisibleToUser() {
        return mIsVisibleToUser;
    }