Android ViewPager片段被调用两次

Android ViewPager片段被调用两次,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,好的,我正试图实现一个有三个页面的ViewPager,并且每个页面上都有唯一的内容,所以我建立了一个系统,在这个系统中,我根据页面索引扩展不同的布局。这在我导航时就起作用了,但是我注意到片段被调用了两次 这是我的碎片活动课程: public class TutorialScreen extends FragmentActivity { private static final String TAG = "TAG"; private static final int NUM_PA

好的,我正试图实现一个有三个页面的ViewPager,并且每个页面上都有唯一的内容,所以我建立了一个系统,在这个系统中,我根据页面索引扩展不同的布局。这在我导航时就起作用了,但是我注意到片段被调用了两次

这是我的碎片活动课程:

public class TutorialScreen extends FragmentActivity {

    private static final String TAG = "TAG";
    private static final int NUM_PAGES = 3;
    private ViewPager pager; // animation handler
    private PagerAdapter adapter; // provides pages to pager

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tutorial_layout);

        // Instantiate Pager & Adapter
        pager = (ViewPager) findViewById(R.id.pager);
        adapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
        pager.setAdapter(adapter);
        Log.v(TAG, "Initial Page is " + pager.getCurrentItem()); // this logs '0' - which is what i want
        pager.setCurrentItem(pager.getCurrentItem());
    }

    @Override
    public void onBackPressed() {
        if(pager.getCurrentItem() == 0) {
            super.onBackPressed();
        }
        else {
            pager.setCurrentItem(pager.getCurrentItem() -1);
        }
    }

    // Pager Adapter SubClass
    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {

        public ScreenSlidePagerAdapter(FragmentManager fm) {
            super(fm);
            Log.v(TAG, "constructor"); // this logs once
            pager.setCurrentItem(pager.getCurrentItem());
        }

        @Override
        public Fragment getItem(int position) {
            Log.v(TAG, "getItem " + position); // this logs twice
            return new ScreenSlidePageFragment(position); // note I've overridden the constructor
        }

        @Override
        public int getCount() {
            return NUM_PAGES;
        }   
    } 
}
还有我的片段类:

public class ScreenSlidePageFragment extends Fragment {

    private static int pageIndex;
    private static final String TAG = "TAG";

    ScreenSlidePageFragment(int id) {
        pageIndex = id;
        Log.v(TAG, "Page Index is " + pageIndex); // this logs twice
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        int resID = -1;

        switch(pageIndex) {
            case 0:
                resID = R.layout.tutorial_page1;
                break;
            case 1:
                resID = R.layout.tutorial_page2;
                break;
            case 2:
                resID = R.layout.tutorial_page3;
                break;
            default:
                resID = R.layout.tutorial_page1;
                break;
        }

        Log.v(TAG, "Res Index is " + resID); // this logs twice
        ViewGroup rootView = (ViewGroup) inflater.inflate(resID, container, false);
        return rootView;
    }
}
日志是

建造师 获取项目0 页面索引为0 获取项目1 页面索引为1 Res指数为2130903043 Res指数为2130903043

因此,基本上它是立即跳转到第二页,不管我是否使用setCurrentItem()设置位置

我想我可能是在作弊,试图只拥有一个片段类,而不是为每个匹配的布局单独创建一个片段类,但是。。。这应该行吗

请注意,我看到了一个(我认为)相关的问题,即第二个(初始)页面显示了两次——一次是初始页面,然后再滑动到下一个页面(应该是第3页?)。一旦我导航到第3页(在两次滑动之后),我就可以一直返回到第1页(应该是初始页)

想法?我做错了什么?

所以,我解决了我自己的(根)问题(尽管不是我遇到的奇怪的索引案例)

我对ViewPager中每个页面的单个内容实例化的误解是,会有一个片段被反复使用,我会将参数传递给它的构造函数,以便告诉它膨胀哪个布局

相反,我意识到我应该拥有完全独立的片段类,每个类都拥有自己独特的布局,并且我可以使用FragmentStatePagerAdapter中getItem()的相同位置id来实例化正确的片段。。。现在对我来说有意义了

见下面的代码:

public class TutorialScreen extends FragmentActivity {

    private static final int NUM_PAGES = 3;
    private ViewPager pager; 
    private PagerAdapter adapter; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tutorial_layout);

        // Instantiate Pager & Adapter
        pager = (ViewPager) findViewById(R.id.pager);
        adapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
        pager.setAdapter(adapter);
    }

    @Override
    public void onBackPressed() {
        if(pager.getCurrentItem() == 0) {
            super.onBackPressed();
        }
        else {
            pager.setCurrentItem(pager.getCurrentItem() -1);
        }
    }

    // PagerAdapter SubClass
    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {

        public ScreenSlidePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            Fragment fragment;
            switch(position) {
                case 0:
                    fragment = new TutorialPage1();
                break;
                case 1:
                    fragment = new TutorialPage2();
                break;
                case 2:
                    fragment = new TutorialPage3();
                break;
                default:
                    fragment = new TutorialPage1();
                break;
            }
            return fragment;
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

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

    } /* EOC */

} /* EOC */ 

所以,我使用的是相同的片段。 适配器:

公共类IncomeWeekFragmentAdapter扩展FragmentStatePagerAdapter{
列表标题列表;
列出日期;
public IncomeWeekFragmentAdapter(碎片管理器格式、列表标题、列表日期){
超级(fm);
this.titlesList=标题;
this.reqDates=reqDates;
}
@凌驾
公共片段getItem(int位置){
片段=空;
Bundle args=新Bundle();
if(片段==null)
片段=新的IncomeWeekFragment();
如果(位置==0){
args.putString(“date_start”,requdates.get(1));
args.putString(“date_end”,requdates.get(0));
}否则如果(位置==1){
args.putString(“date_start”,requdates.get(3));
args.putString(“date_end”,requdates.get(2));
}否则如果(位置==2){
args.putString(“date_start”,requdates.get(5));
args.putString(“date_end”,requdates.get(4));
}否则如果(位置==3){
args.putString(“date_start”,requdates.get(7));
args.putString(“date_end”,requdates.get(6));
}
fragment.setArguments(args);
返回片段;
}
@凌驾
public int getCount(){
返回计数\收入\片段;
}
@凌驾
public int getItemPosition(@NonNull Object){
返回位置\无;
}
@可空
@凌驾
公共字符序列getPageTitle(int位置){
返回titlesList.get(位置);
}
}

默认情况下,将加载左侧和右侧的片段(最初右侧只有一个片段)。这样做是出于性能原因,因此在分页时可以有平滑的动画。您可以增加每侧预加载的数量,但最小值为1。好的,这是有意义的(我记得在transformPage()方法中提到过这一点)。。。但为什么要浏览/设置第二页?我应该在别处调用setCurrentItem()吗?根据您的日志,它看起来像是在创建第0页和第1页(在后台)。是什么让你觉得第1页显示了两次?另外,行
pager.setCurrentItem(pager.getCurrentItem())
不执行任何操作,因此您最好将其删除。pager.getCurrentItem()记录“0”,因此我想使用它而不是pager.setCurrentItem(0)以避免出现幻数…第0页从未显示-第1页是初始屏幕。右击后,第1页再次显示,然后是第2页,然后是第3页。只有到了第3页我才能回到第0页…你的代码片段在每次装入和旋转手机时调用两次,你能修复吗?嗯。。。是的,但我认为这超出了原始问题的范围……你能检查一下我的代码吗?请我有这个问题,我不能把一个新问题贴出来并链接到这里,但是如果你有,比如说二十个不同的片段,你只需要在每个片段上改变一些东西,你真的想创建二十个不同的布局吗?
public class IncomeWeekFragmentAdapter extends FragmentStatePagerAdapter {

    List<String> titlesList;
    List<String> reqDates;

    public IncomeWeekFragmentAdapter(FragmentManager fm, List<String> titles, List<String> reqDates) {
        super(fm);
        this.titlesList = titles;
        this.reqDates = reqDates;
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;
        Bundle args = new Bundle();
        if(fragment==null)
        fragment = new IncomeWeekFragment();
        if (position == 0) {
            args.putString("date_start", reqDates.get(1));
            args.putString("date_end", reqDates.get(0));
        } else if (position == 1) {
            args.putString("date_start", reqDates.get(3));
            args.putString("date_end", reqDates.get(2));
        } else if (position == 2) {
            args.putString("date_start", reqDates.get(5));
            args.putString("date_end", reqDates.get(4));
        } else if (position == 3) {
            args.putString("date_start", reqDates.get(7));
            args.putString("date_end", reqDates.get(6));
        }
        fragment.setArguments(args);
        return fragment;
    }

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

    @Override
    public int getItemPosition(@NonNull Object object) {
        return POSITION_NONE;
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return titlesList.get(position);
    }
}