View pager and fragment lifecycle

后端 未结 7 1034
滥情空心
滥情空心 2020-12-02 14:09

I have a ViewPager that loads three pages at a time. If I swipe from page 1 to page 2 then to 3, the first page(fragment) goes to onPause(). Then, if I swipe t

相关标签:
7条回答
  • 2020-12-02 14:47

    The fragment's lifecycle methods are not called when swiping between fragments. You can use ViewPager.SimpleOnPageChangeListener to solve this problem. The sample code is as bellow (in Kotlin).

    // other code
    mViewPager.addOnPageChangeListener(object: ViewPager.SimpleOnPageChangeListener() {
        override fun onPageSelected(position: Int) {
            val oldPosition = mViewPager.currentItem
            val oldFragment = mViewPager.adapter?.instantiateItem(mViewPager, oldPosition)
            oldFragment.onPauseStuff() // Hint: do as here call onPause
            val newFragment = mViewPager.adapter?.instantiateItem(mViewPager, position)
            newFragment.onResumeStuff() // Hint: do as here call onResume
    }
    // other code
    
    0 讨论(0)
  • 2020-12-02 14:49

    if your Fragment extend android.support.v4.app.Fragment

    you can use this, it works for me.

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (!isVisibleToUser) {
            //do sth..
        }
    }
    
    0 讨论(0)
  • 2020-12-02 14:56

    The FragmentPagerAdapter keeps additional fragments, besides the one shown, in resumed state. The solution is to implement a custom OnPageChangeListener and create a new method for when the fragment is shown.

    1) Create LifecycleManager Interface The interface will have two methods and each ViewPager’s Fragment will implement it. These methods Are as follows:

    public interface FragmentLifecycle {
    
        public void onPauseFragment();
        public void onResumeFragment();
    
    }
    

    2) Let each Fragment implement the interface Add iplements statement for each class declaration:

    public class FragmentBlue extends Fragment implements FragmentLifecycle
    public class FragmentGreen extends Fragment implements FragmentLifecycle
    public class FragmentPink extends Fragment implements FragmentLifecycle
    

    3) Implement interface methods in each fragment In order to check that it really works as expected, I will just log the method call and show Toast:

    @Override
    public void onPauseFragment() {
        Log.i(TAG, "onPauseFragment()");
        Toast.makeText(getActivity(), "onPauseFragment():" + TAG, Toast.LENGTH_SHORT).show(); 
    }
    
    @Override
    public void onResumeFragment() {
        Log.i(TAG, "onResumeFragment()");
        Toast.makeText(getActivity(), "onResumeFragment():" + TAG, Toast.LENGTH_SHORT).show(); 
    }
    

    4) Call interface methods on ViewPager page change You can set OnPageChangeListener on ViewPager and get callback each time when ViewPager shows another page:

    pager.setOnPageChangeListener(pageChangeListener);
    

    5) Implement OnPageChangeListener to call your custom Lifecycle methods

    Listener knows the new position and can call the interface method on new Fragment with the help of PagerAdapter. I can here call onResumeFragment() for new fragment and onPauseFragment() on the current one.

    I need to store also the current fragment’s position (initially the current position is equal to 0), since I don’t know whether the user scrolled from left to right or from right to left. See what I mean in code:

    private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
    
        int currentPosition = 0;
    
        @Override
        public void onPageSelected(int newPosition) {
    
            FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
            fragmentToShow.onResumeFragment();
    
            FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
            fragmentToHide.onPauseFragment();
    
            currentPosition = newPosition;
        }
    
        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) { }
    
        public void onPageScrollStateChanged(int arg0) { }
    };
    

    I didn't write the code. Full tutorial here: http://looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-including-source-code/

    0 讨论(0)
  • 2020-12-02 14:57

    Override setUserVisibleHint(). This method will call once the fragment is visible to the user.

    0 讨论(0)
  • 2020-12-02 15:03

    Solve your problem:

    public class FragmentVisibleHelper implements LifecycleObserver {
    
        private static final String TAG = "VipVisibleHelper";
    
        public interface IVisibleListener {
    
            void onVisible();
    
            void onInVisible();
        }
    
        boolean mIsVisibleToUser;
        boolean mStarted = false;
    
        volatile boolean mIsCalledVisible = false;
        volatile boolean mIsCalledInvisible = false;
    
    
        IVisibleListener mListener;
    
        public void setListener(IVisibleListener mListener) {
            this.mListener = mListener;
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        void onResume() {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "onResume() called:"));
            if (mIsVisibleToUser) {
                dispatchVisible();
            }
        }
    
        private void dispatchVisible() {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
            if (!mIsCalledVisible) {
                mIsCalledVisible = true;
                mIsCalledInvisible = false;
    
                if (Profile.LOG) {
                    Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called onVisible"));
                }
    
                if (mListener != null) {
                    mListener.onVisible();
                }
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        void onPause() {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "onPause() called:"));
            if (mIsVisibleToUser) {
                dispatchInvisible();
            }
        }
    
        private void dispatchInvisible() {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
            if (!mIsCalledInvisible) {
                mIsCalledInvisible = true;
                mIsCalledVisible = false;
    
                if (Profile.LOG) {
                    Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called onInVisible"));
                }
    
                if (mListener != null) {
                    mListener.onInVisible();
                }
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        void onStart() {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "onStart() called"));
            mStarted = true;
            if (mIsVisibleToUser) {
                dispatchVisible();
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        void onStop() {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "onStop() called"));
            if (mIsVisibleToUser) {
                dispatchInvisible();
            }
            mStarted = false;
        }
    
        public void setUserVisibleHint(boolean isVisibleToUser) {
            Log.d(TAG, String.format("%-60s %s", this.toString(), "setUserVisibleHint() called with: isVisibleToUser = [" + isVisibleToUser + "]:"));
            mIsVisibleToUser = isVisibleToUser;
            if (mStarted) { // fragment have created
                if (mIsVisibleToUser) {
                    dispatchVisible();
                } else {
                    dispatchInvisible();
                }
            }
        }
    
        public boolean isVisibleToUser() {
            return mIsVisibleToUser;
        }
    }
    
    0 讨论(0)
  • 2020-12-02 15:04

    Override setUserVisibleHint() this will call when fragment is visible to the user

    0 讨论(0)
提交回复
热议问题