当前位置: 首页 > 知识库问答 >
问题:

FragmentPagerAdapter和FragmentStatePagerAdapter

周云
2023-03-14

我目前正在考虑应该使用PagerAdapter的哪个实现。我对他们俩都有两难的选择。让我给你看看这些是什么。

1#FragmentPagerAdapter

工作良好,当没有以前的实例可用时,它会创建片段的新实例,当有这样的机会时,它会检索以前的片段。

那不是很低效吗?我在Google I/O materials上看到Romain Guy说,创建新的视图效率不高,特别是当我们创建大量视图时,就像在ListView中那样,因此我们使用ConvertView检索现有的视图并根据需要多次更改它。因此页面之间的翻转非常相似--许多新的视图--因为fragment是某种视图

在两个 PagerAdapter中,我尝试了重写 destroyItem()方法,但根本不起作用。

我的问题是。

我该怎么办?

我应该使用SharedPreference和选项#1来配合FragmentPagerAdapter还是使用选项#2来配合FragmentStatePagerAdapter

有没有可能,我在这些适配器中做错了什么,使它们的行为不像我们预期的那样?

/**
 * Adapter class to {@link WizardPager}
 */
public static class WizardCrazyAdapter extends FragmentStatePagerAdapter
    implements OnPageChangeListener{

    public static final String tag = "android:switcher:"+R.id.pager_w+":";

    /**
     * Refernece to root activity
     */
    WizardActivity wizardActivity;

    /**
     * list of fragments
     */
    private final ArrayList<FragmentInfo> fInfos = new ArrayList<FragmentInfo>();

    private short prevPageNumber = 0;

    /**
     * Constructor of adapter
     * @param wizardActivity
     *            {@link WizardActivity} as reference to activity root
     */
    public WizardCrazyAdapter(WizardActivity wizardActivity) {
        super(wizardActivity.getSupportFragmentManager());
        this.wizardActivity = wizardActivity;           
    }

    static final class FragmentInfo {
        private final Class<?> _clss;
        private Bundle _args;

        public FragmentInfo(Class<?> clss, Bundle args) {
            _clss   =clss;
            _args   =args;
        }
    }

    public void addPage(Class<?> clss, Bundle args){
        FragmentInfo fi = new FragmentInfo(clss, args);         
        fInfos.add(fi);
    }

    /**
     * Return number of pages
     */
    public int getCount() {
        return fInfos.size();
    }
    /**
     * Searches in {@link FragmentManager} for {@link Fragment} at specified position
     * @param position
     * @return
     */
    private AbstractWizardFragment getFragmentAt(int position){
        FragmentManager fm = wizardActivity.getSupportFragmentManager();

        AbstractWizardFragment awf = (AbstractWizardFragment) fm.findFragmentByTag(tag+position);

        return awf;         
    }

    /**
     * Return page of view pager
     */
    @Override
    public Fragment getItem(int position) {
        /*finding existing instance of fragment*/
        AbstractWizardFragment awf = getFragmentAt(position);

        if(awf == null){
            /*creating new instance if no instance exist*/
            Log.v("WizardActivity", "creating new Fragment");
            FragmentInfo fi = fInfos.get(position);
            awf = (AbstractWizardFragment) Fragment.instantiate(wizardActivity, fi._clss.getName());
        }else{
            Log.v("WizardActivity", "found existing Fragment");
        }

        return awf;
    }
    @Override
    public void onPageSelected(int pageNumber) {
        wizardActivity.stepFragment.setCurrentStepAndChangeText(pageNumber);

        if(pageNumber != prevPageNumber){
            AbstractWizardFragment prevFragment = (AbstractWizardFragment) getItem(prevPageNumber);//TODO change if any problems
            prevFragment.onDetachedFromViewPager(wizardActivity.mForm);
        }

        AbstractWizardFragment currFragment = (AbstractWizardFragment) getItem(pageNumber);//TODO change if any problems
        currFragment.onAttachedToViewPager(wizardActivity.mForm);

        prevPageNumber = (short) pageNumber;


        Log.d("WizardActivity", "onPageSelected");
    }

    @Override
    public Object instantiateItem(ViewGroup arg0, int arg1) {
        Log.d("WizardActivity", "instantiateItem "+arg1);
        return super.instantiateItem(arg0, arg1);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
   //           super.destroyItem(container, position, object);

        Log.v("WizardActivity", "that would be destroy");
    }
}

ViewPager代码

public class WizardPager extends ViewPager{

/**
 * Flag to check if view pager must be scrolled 
 */
protected boolean isScrollable;

/**
 * Default constructor
 * @param context {@link Context}
 */
public WizardPager(Context context) {
    super(context);
    isScrollable = true;
}

/**
 * Standard constructor
 * @param context {@link Context}
 * @param attrs {@link AttributeSet}
 */
public WizardPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    isScrollable = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.isScrollable) {
        return super.onTouchEvent(event);
    }

    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.isScrollable) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

/**
 * Enable scroll of pages
 */
public void enableScroll(){
    this.isScrollable = true;
}

/**
 * Disable scroll of pages
 */
public void disableScroll(){
    this.isScrollable = false;
}

/**
 * Check if pages can be scrolled
 * @return
 */
public boolean isScrollable(){
    return isScrollable;
}
}

共有1个答案

武博艺
2023-03-14

我在OnPageSelectedMethod中搞砸了--我强制FragmentStatePagerAdapter调用GetItem--每当页面发生更改时,它至少实例化片断一次--方法。这就是为什么我抱怨每次更改页面时都要实例化Fragment:)

而不是getItem(),我应该在那里调用我的getFragmentat()方法,整个回调应该是这样的。

@Override
public void onPageSelected(int pageNumber) {
    wizardActivity.stepFragment.setCurrentStepAndChangeText(pageNumber);

    if(pageNumber != prevPageNumber){
        AbstractWizardFragment prevFragment = (AbstractWizardFragment) getFragmentAt(prevPageNumber);
        prevFragment.onDetachedFromViewPager(wizardActivity.mForm);
    }

    AbstractWizardFragment currFragment = (AbstractWizardFragment) getFragmentAt(pageNumber);
    currFragment.onAttachedToViewPager(wizardActivity.mForm);

    prevPageNumber = (short) pageNumber;


    Log.d("WizardActivity", "onPageSelected");
}

虽然它工作得很好。仍然可能存在这样的风险,即找不到fragment并且方法将返回null,然后将引发NPE。

 类似资料:
  • 和之间有什么区别? 关于,Google的指南说: 这个版本的分页器最适合在有几个典型的更静态的片段要分页时使用,比如一组选项卡。用户访问的每个页面的片段将保留在内存中,尽管其视图层次结构在不可见时可能会被破坏。这会导致使用大量内存,因为片段实例可以保持任意数量的状态。对于较大的页集,请考虑。 和关于: 这个版本的分页器在有大量页面时更有用,工作起来更像列表视图。当页面对用户不可见时,其整个片段可能

  • 由于API 27已弃用。对此最好的替代方案是什么? 在我的例子中,我知道需要使用之类的东西,但我不知道在我的代码中这需要去哪里。 我在班上得到了这些进口货: 但是 被划掉了。

  • 我有一个警告:FragmentPagerAdapter已弃用。这是我的代码: 我在这里找到了一个可能的解决方案:片段页面适配器已弃用 但它在Kotlin中。 警告的字眼是:超级

  • 我有一个ViewPager有3个碎片绑定在FragmentPagerAdapter在一个FragmentActivity中,当我切换到不同的应用程序,回到我的应用程序后,或者在一个输入调用后,碎片没有恢复到以前的状态,一个碎片完全消失了,一些碎片按钮点击不工作..但在模拟器中它的工作很好 帮帮我吧...

  • 我有一个带选项卡指示器的viewPager。ViewPager是带有FragmentPagerAdapter的setAdaper。 我几乎不了解FragmentPagerAdapter的内部是如何工作的。我注意到邻居片段被恢复(调用OnResume),即使邻居还不可见。 我把更新方法放在OnResume中,以为片断是最新的,它就会更新。 广告横幅刷新 我希望页脚中设置的广告横幅在向左滑动一次或向右