Programing

조각 수명주기-표시 / 숨기기시 어떤 메서드가 호출됩니까?

crosscheck 2020. 8. 30. 07:41
반응형

조각 수명주기-표시 / 숨기기시 어떤 메서드가 호출됩니까?


다음 방법을 사용하여 조각을 표시 / 숨겨서 (내 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;
    }

내가 명확하지 않은 것은 Fragments 수명주기의 어떤 메소드를 표시하거나 숨길 때 호출되는지입니다. (onShow () 또는 onHide ()와 같은 메소드가 없기 때문에 무엇을 사용 해야할지 모르겠습니다.) 특정 조각을 표시하고 숨길 때 특정 작업을 수행하고 싶습니다.


액티비티 수명주기와 마찬가지로 Android는 조각이 표시되면 onStart ()를 호출합니다 . onStop()일반적으로 조각이 보이지 않을 때 호출되지만 나중에 호출 될 수도 있습니다.

레이아웃에 따라 Android는 onStart()Fragment가 아직 표시되지 않지만 표시되는 상위 컨테이너에 속할 때도 호출 할 수 있습니다 . 예를 들어, 메서드 android.support.v4.view.ViewPager를 재정의해야하는 경우에 유효합니다 Fragment.setUserVisibleHint(). 어쨌든 BroadcastReceivers 또는 다른 리스너를 등록 / 등록 해제해야하는 경우 onStart()onStop()메서드는 항상 호출되므로 안전하게 사용할 수 있습니다 .

참고 : 일부 조각 컨테이너는 보이지 않는 조각을 시작 상태로 유지할 수 있습니다. 이 상황을 처리하기 위해 Fragment.onHiddenChanged(boolean hidden). 문서 에 따르면 사용자가 볼 수 있도록 조각이 시작되고 표시 되어야합니다 (숨겨지지 않음) .

업데이트 : 사용 android.support.v4.widget.DrawerLayout하면 서랍 아래의 조각이 시작된 상태로 유지되고 서랍이 열려 있어도 표시됩니다. 이 경우 콜백 을 사용 DrawerLayout.setDrawerListener()하고 수신 해야합니다 .onDrawerClosed()onDrawerOpened()


이 방법을 @Override하고 내 문제를 해결합니다.

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

뷰 페이저 동작의 조각은 일반 조각 컨테이너와 다릅니다.

이 코드를 시도하십시오.

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

이 코드를 시도하십시오.

@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();
  }
}

조각이 표시되고 활동에서 뷰 페이지를 사용하는 경우 조각 메서드를 호출하는 또 다른 방법입니다.

// 먼저 인터페이스를 만듭니다.

public interface ShowFragmentVisible{
      public void showFragment();}

// 그 후이 인터페이스는 Fragment 내부에서 구현됩니다.

      public class MyFragment extends Fragment implements 
         ShowFragmentVisible {
            @Override
public void showFragment() {
}

// Now goes your Activity then create object of interface and call inside when 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

You can use 'onCreateView'(or 'onActivityCreated') and 'onHiddenChanged'. Use 'onCreateView' for first show and use 'onHiddenChanged' for later. 'setMenuVisibility' is not called on transaction control.

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

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

setUserVisibleHint call before onCreateView. and you can't update any View inside setUserVisibleHint I use

public void setMenuVisibility(final boolean visible)

for visibility and onHiddenChanged() didn't call for the first time. it calls when the hidden state changes. because a fragment is visible by default. In order to achieve this method for the first time you have to call mFragmentTransaction.hide(oldFragment) then it will work

Note

if you want to use setUserVisible hint and update View Use this method


Of course you could override setUserVisibleHint or setMenuVisibility but if you need to access Context or Activity, they will be null in there! There is another method onStart which always has the context available at hand, but it will only get called once upon creation of fragment and if you start moving between your fragments in a pager you will see that it won't get called in second view and afterwards.

So... what to do now?

The workaround is quite easy, use onStart for the first visit and setMenuVisibility for later ones. Your code will probably look like below :

Fragment class:

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();
}

This way Context will always be available to doSth() method.

참고URL : https://stackoverflow.com/questions/18375288/fragment-lifecycle-which-method-is-called-upon-show-hide

반응형