4

我目前正在考慮應該使用PagerAdapter的哪個實現。 我已經有兩難困境了。讓我告訴你這些是什麼。FragmentPagerAdapter和FragmentStatePagerAdapter

1#FragmentPagerAdapter

做工精細,它創建片段的新實例時沒有以前的實例可用,並檢索以前的時候有這樣的機會片段。

我已經在計算器上最近讀了,方法PagerAdapter'sgetItem()方法被調用,只有當它需要創建片段,但 - 它被稱爲一遍又一遍,我不得不處理創建新實例和檢索在此方法中的舊身體。

但是 - 只有很少的回調和生命週期方法被調用。例如我不能設法調用onSaveInstanceState。所以沒有辦法保存片段的狀態 - 當然我可以使用SharedPreferences或其他東西,但我想使用回調方法。有什麼辦法可以實現嗎?

2#FragmentStatePagerAdapter

完美地工作,節省每次ViewPager保持片段的狀態。

但 - 這PagerAdapter總是創建新的片段。我在構造函數中檢查它。

這不是沒有效率嗎?我在Google I/O資料中看到Romain Guy說創建新的Views效率不高,尤其是當我們在ListView中創建大量Views時,所以我們使用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 - 它實例片段至少一次 - 只要方法頁面改變。這就是爲什麼我抱怨實例片段每次頁面被改變:)

相反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將不會被找到,並且該方法將返回空值 - 然後將導致NPE拋出。

相關問題