使用Fragment Pager Adapter时,getItem()方法被调用两次。

6
我正在使用一个片段页适配器来实例化我的片段类。我能够这样做,但我的问题是我的getItem()方法被调用了两次,这会在后续造成问题。你能解释一下为什么会发生这种情况吗?
    package com.creatiosoft.rssfeed.adaptor;

    import android.content.Context;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.util.Log;

    import com.creatiosoft.rssfeed.utils.RssItem;
    import com.viewpagerindicator.IconPagerAdapter;

    public class NewsFeedsAdapter extends FragmentPagerAdapter implements
            IconPagerAdapter {

        int[] icon = null;
        String[] content = null;
        String[] URLs = null;
        Context cont;

        public NewsFeedsAdapter(FragmentManager fm, Context context) {
            super(fm);
            Log.i("jk", "constructor");
            this.cont = context;
            RssItem newsFeedAppliaction = (RssItem) cont;
            /*
             * Retrieving the values of the Icons and contents from the application
             * class in utils package
             */
            icon = newsFeedAppliaction.getICONS();
            content = newsFeedAppliaction.getCONTENT();
            URLs = newsFeedAppliaction.getURL();

        }

        /** instantiate a new fragment class */
        @Override
        public Fragment getItem(int position) {
            Log.i("yt", "hello" + position);
            return TestFragment.newInstance(position % content.length, cont);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return content[position % content.length].toUpperCase();
        }

        public int getIconResId(int index) {
            return icon[index];
        }

        /** return the no of views on the basis of array items */
        @Override
        public int getCount() {

            Log.i("hi", "length" + content.length);
            return content.length;
        }
    }      

我正在使用以下代码调用适配器:
NewsFeedsAdapter adapter = new NewsFeedsAdapter(
                getSupportFragmentManager(), getApplicationContext());
        /**
         * get the id of the view pager declared in the xml resource and set the
         * adaptor on the view pager
         */
        ViewPager pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(adapter);
        //pager.setCurrentItem(0);

        /**
         * Tab page indicator class is used to indicate the tabs and is accessed
         * from the library class
         */
        TabPageIndicator indicator = (TabPageIndicator) findViewById(R.id.indicator);
        indicator.setViewPager(pager);  
3个回答

12

请注意,分页器至少保留一个页面预加载。这意味着当创建分页器时,他会创建至少两个页面-他展示的页面和下一个页面,以便允许"翻页"。


2
在您的getItem方法中,您创建了一个新的fragment实例。这是可怕的。它让您处于现在的情况下。您正在创建一个新的匿名项,它将按照您指定的方式生存下来。但是当邪恶的Android系统再次决定需要与您的Fragment通信并从您的适配器请求它时,您会告诉它“不,我不想!”而是给它一个完全相同的旧兄弟片段的新片段。
要解决此问题,请预先填充所有片段,然后返回正确的片段。或者如果您愿意,不这样做。但是记录已创建的实例,以便您可以返回已创建的片段。
我不知道为什么它会被调用两次-我还没有搜索过v4的源代码,但这可能是为了确保实际检索该项,或者系统进入了需要刷新先前项的状态。
总之,保留已创建的实例-特别是对于像fragments、views和activities这样沉重的对象。
class Adapter extends MyWhateverAdapter {
    Fragment[] myLovelyFragments;

    public Adapter() {
        // Instantiate your fragments and place them into myLovelyFragments
    }

    public int getFragmentCount() {
        return myLovelyFragments.length;
    }

    public Fragment getItem(int position) {
        return myLovelyFragments[position];
    }
}

@Rishabh.CreatioSoft 给你。 :) - ahodder
但是告诉我一件事,当 PagerAdapter 调用 getItem 时,位置会同时返回 0 和 1。因此,我们在第一个位置上获取了 fragment 对象。那么你怎么能说你的代码是正确的呢? - Rishabh Agrawal
@Rishabh.CreatioSoft,很抱歉,我不理解你的最后一条评论。我的适配器与Android的Base适配器非常相似。如果您担心如何在位置0获取片段,则我认为您需要重新查看数组的索引方式。数组的索引是0-n-1。因此,如果您有两个片段位于位置0和1,则只需调用getItem(0)或getItem(1)。 - ahodder
我遇到了同样的问题。我有两个页面,但每次首次加载分页器时,第一页也会被调用两次。 - deathemperor
@AedonEtLIRA 你太棒了!!!我一直在为这个该死的问题奋斗了7个小时!但是你帮我解决了它!!!非常感谢。 - Mehdi Jahed Manesh
@ahodder,你说这是“可怕的”,但官方文档建议与OP相同的方法:https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter - 即,public Fragment getItem(int position) { return ArrayListFragment.newInstance(position); } - ban-geoengineering

0

你可能遇到的问题不是多次调用getItem()方法。经过一番研究,我发现方法isViewFromObject()扮演了重要的角色,在它的文档中提到"该方法对于 PagerAdapter 的正常运行是必需的。"

我还发现实现该方法的正确方式是:

@Override
public boolean isViewFromObject(View view, Object object) {
    if(object != null){
        return ((Fragment)object).getView() == view;
    }else{
        return false;
    }
}

你可以在这里查看。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接