始终为索引0和1调用Viewpager Adapter getItem

我只是想知道viewpager及其适配器的正常行为是否始终为索引0和1调用getItem()方法,即使我立即设置了当前位置

这是我的代码:

 mNewsPagerAdapter = new NewsDetailPagerAdapter(getChildFragmentManager()); mNewsPagerAdapter.updateNewsList(news); mViewPager = (ViewPager) mView.findViewById(R.id.horizontal_view_pager); mViewPager.setPageMargin(2); mViewPager.setPageMarginDrawable(R.color.black); mViewPager.setAdapter(mNewsPagerAdapter); mViewPager.setCurrentItem(mCurrentPositionPager, false); 

如果我使用此viewpager从概览活动切换到我的详细活动,则适配器始终调用位置0和1的getItem()方法,然后mOriginalPosition及其邻居的位置的getItem()方法。 我想知道这是否是正确的行为,或者我错过了以正确的方式实现它的东西。 谢谢你的帮助 :)

编辑:添加了我的适配器代码

 public class NewsDetailPagerAdapter extends FragmentStatePagerAdapter { private SparseArray mPageReferenceMap = new SparseArray(); private ArrayList mNewsList; public NewsDetailPagerAdapter(FragmentManager fm) { super(fm); } /** * Setzt die neuen News. **/ public void updateNewsList(ArrayList list) { mNewsList = list; } @Override public Fragment getItem(int position) { Log.d("debug", "getItem position:" + position); News newsItem = mNewsList.get(position); NavigationFragment fragment = new NavigationFragment(); mPageReferenceMap.put(position, fragment); return fragment; } @Override public int getCount() { return mNewsList.size(); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } public Fragment getFragment(int position) { return mPageReferenceMap.get(position); } 

}

实际上这是普通人的行为。 实际上,作为将ViewPager与适配器相关联的soos,适配器会创建第一个可访问布局(索引0)到下一个(索引1)。 默认情况下,这在“setAdapter”中完成。 然后,当您设置不同的位置时,适配器将在所选索引(前一个和下一个索引)处实例化该片段。

这是通常的ViewPager setAdapter代码:

 public void setAdapter(PagerAdapter adapter) { if (mAdapter != null) { mAdapter.setViewPagerObserver(null); mAdapter.startUpdate(this); for (int i = 0; i < mItems.size(); i++) { final ItemInfo ii = mItems.get(i); mAdapter.destroyItem(this, ii.position, ii.object); } mAdapter.finishUpdate(this); mItems.clear(); removeNonDecorViews(); mCurItem = 0; scrollTo(0, 0); } final PagerAdapter oldAdapter = mAdapter; mAdapter = adapter; mExpectedAdapterCount = 0; if (mAdapter != null) { if (mObserver == null) { mObserver = new PagerObserver(); } mAdapter.setViewPagerObserver(mObserver); mPopulatePending = false; final boolean wasFirstLayout = mFirstLayout; mFirstLayout = true; mExpectedAdapterCount = mAdapter.getCount(); if (mRestoredCurItem >= 0) { mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); setCurrentItemInternal(mRestoredCurItem, false, true); mRestoredCurItem = -1; mRestoredAdapterState = null; mRestoredClassLoader = null; } else if (!wasFirstLayout) { populate(); } else { requestLayout(); } } if (mAdapterChangeListener != null && oldAdapter != adapter) { mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); } } 

为了更改ViewPager行为,您可以扩展经典ViewPager,覆盖setAdapter方法并将mCurrItem设置为所需位置。

我希望它有所帮助

编辑:

经过不同的测试,我们find了解决方案。

如果在ViewPager布局可见后设置了ViewPager适配器,则会加载项目0和1。 如果要避免此行为,但在布局变为可见之前无法设置适配器(因为您正在等待数据),则可以使用此变通方法:

1)最初将ViewPager可见性设置为GONE

2)收到所有数据后,更新适配器并设置当前项目值

3)最后,将ViewPager可见性设置为VISIBLE

在这里你可以find一个例子:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.detail_overview_fragment, container, false); final int position = getArguments().getInt("position"); final ViewPager viewPager = (ViewPager) v.findViewById(R.id.viewpager); viewPager.setVisibility(View.GONE); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { viewPager.setAdapter(new PagerAdapter(getChildFragmentManager())); viewPager.setCurrentItem(position); viewPager.setVisibility(View.VISIBLE); } },5000); return v; } 

是的,这是ViewPager的正常行为,因为它总是会尝试通过渲染限制绘图区域的选项卡来保持领先于用户。 我个人不建议创建自定义ViewPager,因为除非你真的知道自己在做什么,否则几乎肯定会破坏function。 您的适配器类应如下所示:

 public class YourCustomPagerAdapter extends FragmentStatePagerAdapter { private List fragmentList = new ArrayList<>(); private List titleList = new ArrayList<>(); public WizardPagerAdapter(FragmentManager fm) { super(fm); } public void addFragment(Fragment fragment, String title) { fragmentList.add(fragment); titleList.add(title); } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public CharSequence getPageTitle(int position) { super.getPageTitle(position); return titleList.get(position); } @Override public int getCount() { return fragmentList.size(); } } 

你应该添加你的片段:

  @Override public void onCreate(Bundle savedInstanceState) { ... YourCustomPagerAdapter adapter = new YourCustomPagerAdapter (getSupportFragmentManager()); adapter.addFragment(FragmentOne.newInstance(), "Frag 1"); adapter.addFragment(FragmentTwo.newInstance(), "Frag 2"); viewPager.setAdapter(adapter); ... } 

这是正常的(在我看来是聪明的)。 ViewPager类有一个名为mOffscreenPageLimit的属性,默认值为1.此数字确定Viewpager将预加载的当前页面左侧和右侧的页数。 例如,您有10页,当前位置为5,mOffcreenPageLimit为1,将加载位置4和6的页面。

您可以通过调用此方法来更改此属性

 viewpager. setOffscreenPageLimit(int) 

如果传入的小于1的整数,则无效。

我认为错误是适配器:

  /** * Setzt die neuen News. **/ public void updateNewsList(ArrayList list) { //mNewsList = list; mNewsList.clear(); mNewsList.addAll(list); /** * Notifies the attached observers that the underlying data has been changed * and any View reflecting the data set should refresh itself. */ this.notifyDataSetChanged(); } 

错误原因:此列表是该适配器的不同实体。