android - ViewPager.setOffscreenPageLimit(0)无法正常工作

我在mViewPager.setOffscreenPageLimit(2)实例中使用的片段是非常耗费资源的,所以我只想一次加载一个。 当我尝试以下内容时:

mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);

我的mViewPager.setOffscreenPageLimit(2)覆盖函数被调用3次,这就是当我调用FragmentStatePagerAdapter.getItem(int position)时会发生的情况。我希望它只被调用一次,因为我指定了0个屏幕外页面。

我相信我正确地调用了所有内容,因为如果我拨打mViewPager.setOffscreenPageLimit(2),则会按照我的预期调用FragmentStatePagerAdapter.getItem(int position)

ViewPager是否需要至少1个屏幕外页面,或者我在这里做错了什么?

10个解决方案
117 votes

我找到的最好的方法是setUserVisibleHint
将此添加到您的片段

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}
Tyler Davis answered 2019-08-13T10:59:37Z
108 votes

ViewPager是否需要至少1个屏幕外页面

是。 如果我正确地阅读源代码,您应该在LogCat中收到有关此内容的警告,例如:

Requested offscreen page limit 0 too small; defaulting to 1
CommonsWare answered 2019-08-13T10:59:05Z
7 votes

你可以尝试这样:

public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}

protected abstract void lazyLoad();
protected void onInvisible(){}
Terry answered 2019-08-13T11:00:08Z
7 votes

先添加

   boolean isFragmentLoaded = false;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && !isFragmentLoaded) {
        //Load Your Data Here like.... new GetContacts().execute();

        isFragmentLoaded = true;
    }
else{
     }
}
Arpit J. answered 2019-08-13T11:00:35Z
1 votes

ViewPager默认加载下一页(片段),您无法通过setOffscreenPageLimit(0)进行更改。 但你可以做点什么来破解。您可以在包含ViewPager的Activity中实现onPageSelected函数。 在下一个片段(你不想加载)中,你编写了一个函数,让我们说showViewContent()你放入所有资源消耗的初始化代码,并且在onResume()方法之前什么也不做。 然后在onPageSelected中调用showViewContent()函数。 希望这会有所帮助。

Friends_little_black answered 2019-08-13T11:01:01Z
1 votes

在我的情况下,我想在视图中启动一些动画,但与setUserVisibleHint有一些问题......
我的解决方案是:

1 / addOnPageChangeListener适用于您的适配器:

mViewPager.addOnPageChangeListener(this);

2 /实现OnPageChangeListener:

public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener

3 /覆盖3个方法:

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{

}

@Override
public void onPageSelected(int position)
{ 
}

@Override
public void onPageScrollStateChanged(int state)
{
}

4 /在您的类上声明并初始化此变量

private static int mTabState = 1;

注意:我的适配器中有三个片段,并使用mTabState作为setCurrentItem和适配器的当前位置,它可以识别哪个片段及时显示给用户...5 /在onPageSelected方法中添加以下代码:

if (mTabState == 0 || position == 0)
    {
        Intent intent = new Intent("animation");
        intent.putExtra("current_position", position);
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
    }

如果上一页或当前页是第0页(位置0中的片段),那么这样做

6 /现在在你的片段类中(适配器位置0的片段),你必须创建广播接收器并在onResume方法中注册它并取消注册onPause方法:

BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (Objects.equals(intent.getAction(), "animation"))
        {
            int currentPosition = intent.getIntExtra("current_position", 0);
            if (currentPosition == 0)
            {
                startAnimation();
                setViewsVisible();
            } else
            {
                setViewsInvisible();
            }
        }
    }
};

@Override
public void onResume()
{
    super.onResume();
    LocalBroadcastManager.getInstance(mContext).registerReceiver(broadcastReceiver, new IntentFilter("animation"));
}

@Override
public void onPause()
{
    super.onPause();
    LocalBroadcastManager.getInstance(mContext).unregisterReceiver(broadcastReceiver);
}

摘要:我有片段寻呼机女巫显示其中的三个片段,我想在适配器的位置0的片段中的视图上显示一些动画,为此我使用BroadcastReceiver。 当拾取片段时,我启动动画方法并向用户显示视图,当片段未向用户显示时,我尝试不可见视图...

AREF answered 2019-08-13T11:02:31Z
0 votes

对于" instantiateItem" 功能,只需准备片段,但不要加载重量级内容。

使用" onPageChangeListener" ,以便每次进入特定页面时,都会加载其重要内容并显示它。

android developer answered 2019-08-13T11:03:03Z
0 votes

这可能是旧线程,但这似乎对我有用。 覆盖此功能:

@Override
public void setMenuVisibility(boolean menuVisible) { 
    super.setMenuVisibility(menuVisible);

    if ( menuVisible ) {
        /**
         * Load your stuffs here.
         */
    } else  { 
        /**
         * Fragment not currently Visible.
         */
    } 
}

快乐的编码......

ralphgabb answered 2019-08-13T11:03:35Z
0 votes

我有同样的问题。 我在这个网站上找到了一些有用的代码并进行了转换。

mViewPager.setOffscreenPageLimit(...)的min int; 是1,所以即使你把它改为0你仍然会加载2页。

首先要做的是创建一个静态int,我们将调用maxPageCount并重写FragmentStatePagerAdapter方法getCount()以返回maxPageCount:

    @Override
    public int getCount() {
        return maxPageCount;
    }

然后创建一个静态方法,可以从程序中的任何位置访问,以允许您更改此maxCount:

public static void addPage(){
    maxPageCount++; //or maxPageCount = fragmentPosition+2
    mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}

现在将maxPageCount初始化为1.如果需要,可以添加另一个页面。在我的情况下,我需要用户在生成另一个之前先处理当前页面。 他这样做,然后,没有问题可以刷到下一页。

希望它对某人有帮助。

K20 answered 2019-08-13T11:04:31Z
0 votes

用这个     //创建boolean以获取数据     private boolean isViewShown = false;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getView() != null) {
        isViewShown = true;
        // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
        fetchData();
    } else {
        isViewShown = false;
    }
} 
Rohit Sharma answered 2019-08-13T11:04:56Z
translate from https://stackoverflow.com:/questions/10073214/viewpager-setoffscreenpagelimit0-doesnt-work-as-expected