103

我在我的ViewPager实例中使用的片段非常耗费资源,所以我只想一次加载一个。当我尝试以下操作时:

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

我的FragmentStatePagerAdapter.getItem(int position)override 函数被调用了 3 次,这就是我调用mViewPager.setOffscreenPageLimit(1). 我希望它只被调用一次,因为我指定了 0 个屏幕外页面。

我相信我正确调用了所有内容,因为如果我调用mViewPager.setOffscreenPageLimit(2),FragmentStatePagerAdapter.getItem(int position)会像我预期的那样被调用 5 次。

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

4

13 回答 13

126

我发现最好的方法是setUserVisibleHint
将它添加到你的片段

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}
于 2014-09-04T23:08:35.777 回答
117

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

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

Requested offscreen page limit 0 too small; defaulting to 1
于 2012-04-09T13:27:29.743 回答
9

You can try like this :

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(){}
于 2015-06-20T01:47:03.817 回答
7

首先添加

   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{
     }
}
于 2015-09-23T05:30:22.360 回答
2

这可能是旧线程,但这似乎对我有用。重写此函数:

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

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

快乐的编码...

于 2014-12-09T01:27:44.377 回答
2

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

于 2015-05-23T08:47:11.170 回答
2

就我而言,我想在视图中开始一些动画,但是 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;

注意:我的适配器中有三个片段,并将 mTab​​State 用于 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 的片段中的视图上显示一些动画,为此我使用广播接收器。选择片段时,我启动动画方法并向用户显示视图,当片段未向用户显示时,我尝试隐藏视图...

于 2018-09-24T11:54:05.657 回答
1

查看只有一页的寻呼机:

这是 2021 年 - 2 月,Alhamdulillah,我只能使用 viewPager 添加一页。该方法是使用 : ViewPagerFragmentPagerAdapterTablayout和 a fragment。就我而言,我可以用 many 填充 many Pagestabs或者只Page用 one填充Tab。当一个标签页和一个页面向左或向右滑动时,我可以设法更改文档的章节(我接下来要显示)。当有很多页面和很多标签时,我可以更改整本书的文档。

在主要的 Activity Oncreate 中:(这是我的工作代码方法,我的工作代码没有改变任何内容):

if(getIntent()!=null){
            if(getIntent().getStringExtra("ONLY_TAFHEEM")!=null)
             sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, true);
            else
            sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, false);
        }else {
            sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, false);
        }

        final ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        tabsLayout = findViewById(R.id.tabs);
        tabsLayout.animate();

        tabsLayout.setupWithViewPager(viewPager);

在适配器中:

 @NonNull
    @Override
    public Fragment getItem(int position) {

          
    // getItem is called to instantiate the fragment for the given page.
    // Return a PlaceholderFragment (defined as a static inner class below).
    return PlaceholderFragment.sendData(mContext, postion, suraName, suraId, ayahId, ARABIC_AYAH, BENGALI_AYAH, actualDbNames[position], tafsirDisplayNames[position]);
}


@Nullable
@Override
public CharSequence getPageTitle(int position) {
   
    return tafsirDisplayNames[position];
}

@Override
public int getCount() {
   // this is the tricky part // Show pages according to array length. // this may only one // this is the tricky part : 
    return tafsirDisplayNames.length;
}

最后是片段公共构造函数:

 public static PlaceholderFragment sendData(Context mContext, int tabIndex, String suraName, String suraId, String ayahNumber, String arabicAyah, String bengaliAyah, String actualDbName, String displayDbName) {

        Log.i("PlaceHolder", "Tafhim sendData: " + bengaliAyah);
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle bundle = new Bundle();
        mContext_ = mContext;
        BENGALI_AYAH = bengaliAyah;
        _DISPLAY_DB_NAME = displayDbName;
        bundle.putInt(ARG_SECTION_NUMBER, tabIndex);
        bundle.putString(SURA_NAME, suraName);
        bundle.putString(SURA_ID, suraId);
        bundle.putString(AYAH_NUMBER, ayahNumber);
        bundle.putString(ARABIC_AYAH, arabicAyah);
        bundle.putString(ACTUAL_DB_NAME, actualDbName);
        bundle.putString(DISPLAY_DB_NAME, displayDbName);
        fragment.setArguments(bundle);
        return fragment;
    }

就是这样,只需将数组(标签标签)传递给适配器,(它可能只有一个元素,以防万一,一页),根据我的需要,我可以填充一页或多页,并据此填充一个选项卡或多个选项卡:在上面的代码中,数组是:tafsirDisplayNames。我也可以在适配器中手动创建数组,当适配器第一次调用时,或者,在重新创建 MainActivity 时使用 +-elements 重新创建数组。

就是这样,所有,Alhamdulillah,快乐编码.......

于 2021-02-13T15:51:47.983 回答
1

请尝试此代码以解决 Viewpager 中刷新视图的问题......

/* DO NOT FORGET! The ViewPager requires at least “1” minimum OffscreenPageLimit */
int limit = (mAdapter.getCount() > 1 ? mAdapter.getCount() - 1 : 1);
mViewPager.setOffscreenPageLimit(limit);
于 2019-06-03T06:28:15.713 回答
0

对于“instantiateItem”功能,只需准备片段,但不要加载繁重的内容。

使用 "onPageChangeListener" ,这样每次您转到特定页面时,您都会加载其繁重的内容并显示它。

于 2014-07-06T12:41:12.777 回答
0
// step 1: add  BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT FragmentPagerAdapter contractor
   
    public class BottomTabViewPager extends FragmentPagerAdapter {
    
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
    
        public BottomTabViewPager(FragmentManager manager) {
            super(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    
        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }
    
        public void addTabs(String title) {
    
            mFragmentTitleList.add(title);
        }
    
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
            // return null;
        }
    }
    
    
   // step  2:  You can try like this :

    
    public class MyFragment extends Fragment  {
    
       
    
        public MyFragment() {
            // Required empty public constructor
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_ui, container, false);
            
            return view;
        }
    
     @Override
        public void onResume() {
            super.onResume();
            /**
             * Load your stuffs here.
             */
        }
    
      }
于 2021-04-05T08:11:10.160 回答
0

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

mViewPager.setOffscreenPageLimit(...); 的最小值 为 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。您可以随时添加另一个页面。在我的情况下,当我需要用户在生成另一个页面之前先处理当前页面。他这样做,然后可以毫无问题地滑动到下一页。

希望它可以帮助某人。

于 2016-08-20T11:36:32.353 回答
0

使用这个 // 创建用于获取数据的布尔值 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;
    }
} 
于 2018-08-24T11:14:14.593 回答