Android 带有片段的 ViewPager - onPause(), onResume()?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10853611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:14:09  来源:igfitidea点击:

ViewPager with fragments - onPause(), onResume()?

androidandroid-viewpageronresumeonpause

提问by user291701

When using ViewPagerwith fragments, our onPause, onResumemethods are not called when moving between tabs. Is there any way we can figure out in the fragment when we're being made visible or being hidden?

ViewPager与片段一起使用时,在选项卡之间移动时不会调用我们的onPause,onResume方法。当我们被显示或隐藏时,我们有什么办法可以在片段中弄清楚吗?

Unfortunately I have logic in onResume, onPause, like registering with location services, that never get stopped when switching tabs because onPausenever gets called until one exits the whole app.

不幸的是,我在onResume, 中有逻辑onPause,就像注册位置服务一样,在切换选项卡时永远不会停止,因为onPause在退出整个应用程序之前永远不会被调用。

回答by Phix

The ViewPager comes with the OnPageChangeListenerinterface. By setting some flags for the previous and currently shown pages, you can emulate this behavior.

ViewPager 自带OnPageChangeListener接口。通过为之前和当前显示的页面设置一些标志,您可以模拟这种行为。

回答by 3c71

Considering previous solutions are not very clear, here is how I solved it thanks to Phix for his hint:

考虑到以前的解决方案不是很清楚,以下是我的解决方法,感谢 Phix 的提示:

In the OnPageChange() callback:

在 OnPageChange() 回调中:

    Fragment old_fragment = getActiveFragment(old_position);
    Fragment new_fragment = getActiveFragment(new_position);
    old_f.setUserVisibleHint(false);
    old_f.onPause();
    new_f.setUserVisibleHint(true);
    new_f.onResume();

Then in onResume():

然后在 onResume() 中:

    if (getUserVisibleHint())
        /* resume code */

and in onPause():

在 onPause() 中:

    if (!getUserVisibleHint())
        /* pause code */

Here is the getActiveFragment code, avoiding to search for that too:

这是 getActiveFragment 代码,避免搜索:

    return fragmentManager.findFragmentByTag("android:switcher:" + viewPagerId + ":" + position);

NB: Fragment have a isVisible() method, but it doesn't seem to be very consistent, hence the use of UserVisibleHint.

注意:Fragment 有一个 isVisible() 方法,但它似乎不是很一致,因此使用 UserVisibleHint。

EDIT: Replace the UserVisibleHint by a private flag. Worked much better!

编辑:用私有标志替换 UserVisibleHint。工作好多了!

回答by Evan

If you are using Android Support Library (rev 11), you can use getUserVisibleHintor override setUserVisibleHint()to capture the changes visible and hide. Look this post.

如果您使用的是 Android 支持库 (rev 11),您可以使用getUserVisibleHint或覆盖setUserVisibleHint()来捕获可见和隐藏的更改。看看这个帖子

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // do something when visible.
    }
}

回答by savepopulation

Solution 1:

解决方案1:

Define a SparseArrayin your ViewPagers' adapters like below. In this array we'll hold the instance of fragments.

SparseArray在您的ViewPagers' 适配器中定义一个,如下所示。在这个数组中,我们将保存片段的实例。

SparseArray<Fragment> registeredFragments = new SparseArray<>();

And Overrideyour Adapters' instantiateItemmethod.

以及Override您的适配器instantiateItem方法。

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

Also OverridedestroyItemmethod of your ViewPagers

还有OverridedestroyItem你的方法ViewPagers

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

And define a new method to get your ViewPagerFragmentsinstance.

并定义一个新方法来获取您的ViewPagerFragments实例。

public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
} 

Now you can implement your logic with ViewPager'sOnPageChangeListener. Here's an example about how you can implement a viewpager's onPageChangeListener:

现在您可以使用ViewPager'sOnPageChangeListener. 这是一个关于如何实现 viewpager 的示例onPageChangeListener

Define an integer to keep current position:

定义一个整数以保持当前位置:

int currentPos;

yourViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // Empty method
            }

            @Override
            public void onPageSelected(int position) {
                  // This is paused fragment.
                  final Fragment pausedFragment = yourAdapter.getRegisteredFragment(currentPos);

                  // update current position value
                  currentPos = position;

                  // This is resumed fragment
                  final Fragment resumedFragment = yourAdapter.getRegisteredFragment(currentPos);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // Empty method
            }
        });

Finally for restoring instance state update your current position to keep updated in which position user left ViewPager

最后为了恢复实例状态更新您的当前位置以保持更新用户离开的位置 ViewPager

currentPos = yourViewPager.getCurrentItem();

Solution 2:

解决方案2:

For another solution you can find your ViewPagerFragmentsby Tag. You can generate your tag with:

对于另一种解决方案,您可以找到您的ViewPagerFragmentsby Tag。您可以使用以下方法生成标签:

@NonNull
public static String generateViewPagerFragmentTag(int viewPagerId, int position) {
        final StringBuilder tagBuilder = new StringBuilder();
        tagBuilder.append("android:switcher:");
        tagBuilder.append(viewPagerId);
        tagBuilder.append(":");
        tagBuilder.append(position);
        return tagBuilder.toString();
    }

And find your Fragment:

并找到您的Fragment

final Fragment yourFragment = getSupportFragmentManager().findFragmentByTag(generateViewPagerFragmentTag(R.id.your_viewpager, currentPos));

Edit:

编辑:

A few years ago while i was looking a solution for getting ViewPager's current item I tried userVisibleHintin Fragments and noticed that it was not reliable. I'm not sure if it's reliable or not now but still I avoid to use.

几年前,当我在寻找获取ViewPagers 当前项目的解决方案时,我userVisibleHintFragments 中尝试并注意到它不可靠。我不确定它现在是否可靠,但我仍然避免使用。

回答by tainy

You can use below method in Fragment

您可以在以下方法中使用 Fragment

public void setUserVisibleHint(boolean isVisibleToUser){

}

when isVisibleToUser == true, the fragment is shown

isVisibleToUser == true, 片段显示

回答by Anubhav Malik

After some research I found the perfect solution to this.

经过一番研究,我找到了完美的解决方案。

when you are initialising your adapter do it like this:-

当您初始化适配器时,请这样做:-

    import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT;

//(i am using androidx but if you have not yet migrated yet you can use appcompat)

    adapter = new FeedTabsPagerAdapter(getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

After adding this line you'll be getting your onResume() and onPause callbacks perfectly. Please mark it correct solution if this issue is solved by my code .Cheers!

添加此行后,您将完美地获得 onResume() 和 onPause 回调。如果我的代码解决了这个问题,请标记正确的解决方案。干杯!

回答by Phil

A bit late to the party but in my current app I've set the OffScreenPageLimit to 1 for my viewpager, this means the fragments are not cached and each time the view changes it reloads the current fragment

参加聚会有点晚了,但在我当前的应用程序中,我已将 viewpager 的 OffScreenPageLimit 设置为 1,这意味着不会缓存片段,每次视图更改时都会重新加载当前片段

https://developer.android.com/reference/android/support/v4/view/ViewPager.html#getOffscreenPageLimit()

https://developer.android.com/reference/android/support/v4/view/ViewPager.html#getOffscreenPageLimit()

回答by suomi35

To give a bit more definition to the methods in savepopulation's answer:

要对savepopulation的答案中的方法进行更多定义:

yourPager.setOnPageChangeListener(new GridViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int row, int column, float rowOffset, float columnOffset, int rowOffsetPixels, int columnOffsetPixels) {

        }

        @Override
        public void onPageSelected(int row, int column) {
            // When on page selected if position is not specific for you
            // you can find your fragment or you can switch position.
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });