4

В настоящее время я думаю, какую реализацию PagerAdapter следует использовать. У меня есть дилеммы, связанные с обоими из них. Позвольте мне показать вам, что это такое.FragmentPagerAdapter и FragmentStatePagerAdapter

1 # FragmentPagerAdapter

отлично работает, он создает новые экземпляры фрагментов, когда ни один предыдущие экземпляры доступны и отыскивает ранее фрагменты, когда есть такая возможность.

Я недавно прочитал на StackOverflow, что метод PagerAdapter'sgetItem() метод вызывается только тогда, когда нужно создать фрагмент, но - это называется снова и снова, и я должен был справиться с созданием новых экземпляров и извлечением старых внутри этого метода тело.

BUT - Вызывается только несколько методов обратного вызова и жизненного цикла. Например, мне не удастся назвать onSaveInstanceState. Таким образом, нет возможности сохранить состояние фрагмента - конечно, я могу использовать SharedPreferences или что-то еще, но я хотел использовать методы обратного вызова. Есть ли способ сделать это?

2 # FragmentStatePagerAdapter

прекрасно работает, сохраняет состояние каждого фрагмента, который содержит ViewPager.

НО - PagerAdapter ВСЕГДА создает новый фрагмент. Я проверил его внутри конструктора.

Разве это неэффективно? Я видел Romain Guy в материалах ввода-вывода Google, говоря, что создание нового Views неэффективно, особенно когда мы создаем много Views, как в ListView, поэтому мы используем convertView для извлечения существующих View и меняем его для наших целей столько раз, сколько хотим , Так fliping между страницами довольно похожи - много новых Views - потому что фрагмент является своего рода View

В обоих PagerAdapters я попытался трюк с главенствующими destroyItem() метод, но он не работает.

И вот мой вопрос.

Что мне делать?

Должен ли я использовать SharedPreferences и вариант №1 с FragmentPagerAdapter или вариант № 2 с FragmentStatePagerAdapter?

Есть ли какая-то возможность, что я делаю что-то неправильно в этих адаптерах, они ведут себя не так, как мы ожидаем?

Ниже мой код разделен на "читаемую" часть

PagerAdapter часть # 1:

/** 
* 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(); 
    } 

PagerAdapter часть # 2:

/** 
    * 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; 
    } 

PagerAdapter часть # 3:

@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"); 
    } 
} 

Vi ewPager код:

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; 
} 
} 

ответ

4

Я перепутались в 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 будет выброшен.

Смежные вопросы