В настоящее время я думаю, какую реализацию PagerAdapter следует использовать. У меня есть дилеммы, связанные с обоими из них. Позвольте мне показать вам, что это такое.FragmentPagerAdapter и FragmentStatePagerAdapter
1 # FragmentPagerAdapter
отлично работает, он создает новые экземпляры фрагментов, когда ни один предыдущие экземпляры доступны и отыскивает ранее фрагменты, когда есть такая возможность.
Я недавно прочитал на StackOverflow, что метод PagerAdapter's
getItem()
метод вызывается только тогда, когда нужно создать фрагмент, но - это называется снова и снова, и я должен был справиться с созданием новых экземпляров и извлечением старых внутри этого метода тело.
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;
}
}