2012-05-13 121 views
9

我在ViewPager中引用我的片段時遇到問題。我想這樣做是因爲從我的活動中,我想刷新指定位置的片段(例如,當前顯示的片段)。在ViewPager中引用片段

目前,我有這樣的事情:

public static class MyPagerAdapter extends FragmentPagerAdapter { 

    private static final String TAG = "MyPagerAdapter"; 
    private static HashMap<Integer, EventListFragment> mPageReferenceMap = new HashMap<Integer, EventListFragment>(); 

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

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

    @Override 
    public Fragment getItem(int position) { 
     Log.i(TAG, "getItem: "+position); 
     int dateOffset = position-1; 
     EventListFragment mFragment = EventListFragment.newInstance(dateOffset); 
     mPageReferenceMap.put(position, mFragment); 
     return mFragment; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     Log.i(TAG, "destroyItem: "+position); 
     mPageReferenceMap.remove(position); 
     super.destroyItem(container, position, object); 
    } 


    public EventListFragment getFragment(int key) { 
     Log.i(TAG, "Size of pager references: "+mPageReferenceMap.size()); 
     return mPageReferenceMap.get(key); 
    } 
} 

的問題是,destroyItem()被調用往往比getItem(),所以我留下的空引用。如果我不使用destroyItem()清除對被破壞片段的引用......以及我引用不存在的片段。

有沒有什麼好的方法可以用EventListFragment mFragment = EventListFragment.newInstance(dateOffset);創建片段?或者我該怎麼做才能從我的活動(從選項菜單中精確地)刷新ViewPager中的片段?

回答

5

我設法解決它。訣竅是在Activity中創建引用列表,而不是PagerAdapter。它是這樣的:

List<WeakReference<EventListFragment>> fragList = new ArrayList<WeakReference<EventListFragment>>(); 

@Override 
public void onAttachFragment (Fragment fragment) { 
    Log.i(TAG, "onAttachFragment: "+fragment); 
    if(fragment.getClass()==EventListFragment.class){ 
     fragList.add(new WeakReference<EventListFragment>((EventListFragment)fragment)); 
    } 
} 
public EventListFragment getFragmentByPosition(int position) { 

    EventListFragment ret = null; 
    for(WeakReference<EventListFragment> ref : fragList) { 
     EventListFragment f = ref.get(); 
     if(f != null) { 
      if(f.getPosition()==position){ 
       ret = f; 
      } 
     } else { //delete from list 
      fragList.remove(f); 
     } 
    } 
    return ret; 

} 

當然你的片段具有實現getPosition()功能,但我需要這樣的事情,無論如何,所以它不是一個問題。

感謝Alex Lockwood對WeakReference的建議!

+0

我剛剛完成了我的決賽,並決定回來看看你是否有事情工作......很高興我能夠幫助(即使它不是主要問題:P)。 –

+0

問題:不應該將fragList.remove()調用傳遞給弱引用,而不是片段? – gcl1

+0

@Michael:我開始使用這樣的方法,它運作得非常好。但由於fragList包含弱引用,因此似乎這些條目會被垃圾回收處理,儘管您仍然需要它們。我看到getFragmentByPosition()方法有時會返回null,所以我認爲這就是發生了什麼。任何想法如何解決這個問題?謝謝。 – gcl1

3

兩件事情:

  1. 添加下面一行在你活動的onCreate方法(或任何你初始化你ViewPager):

    mPager.setOffscreenPageLimit(NUM_ITEMS-1); 
    

    這將保持在內存中的額外離屏頁面(即防止它們被破壞),即使它們當前沒有顯示在屏幕上。

  2. 您可能會考慮實施您的HashMap,以便它自己保留WeakReference<Fragment>而不是Fragment。請注意,這將要求您更改getFragment方法如下:

    WeakReference<Fragment> weakRef = mPageReferenceMap.get(position); 
    return (weakRef != null) ? weakRef.get() : null; 
    

    這無關你的問題......這只是我注意到了,以爲我會提請你注意。將WeakReferences保留到Fragment將允許您利用垃圾收集器爲您確定可達性的能力,因此您不必親自操作。

+0

至於2. =>它不會解決我的問題,但可能是一個好主意,以防止泄漏,謝謝。並且1. =>我會有7頁,以後可能會更多,可以同時將它們全部保存在內存中嗎? –

+0

嗯......顯然,你在記憶中留下的'碎片'越少越好。如果你想從'Activity'中按需訪問'Fragment'(而不是實際切換到Fragment的頁面)而不是將它們全部保存在內存中,修復將變得更加棘手。它可能需要深入研究'ViewPager'源代碼並瞭解它如何處理'Fragment'生命週期。我不知道有什麼辦法可以做到這一點,但當我有更多時間時我會研究它。 –

+0

我可以謙虛地暗示,如果在屏幕外有任何你需要從片段中獲得的東西,也許你不應該把它放在片段上。考慮將其放入Service或ContentProvider中,並讓您的Fragment成爲它的客戶端。 – Sparky