在ViewPager中引用片段

时间:2012-05-13 18:21:39

标签: android android-fragments

我在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中的片段(从选项菜单中精确)?

2 个答案:

答案 0 :(得分: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提出的建议!

答案 1 :(得分:3)

两件事:

  1. 在活动的onCreate方法中(或初始化ViewPager的任何位置)添加以下行:

    mPager.setOffscreenPageLimit(NUM_ITEMS-1);
    

    这会将额外的屏幕外页面保留在内存中(即防止它们被破坏),即使它们当前没有显示在屏幕上也是如此。

  2. 您可以考虑实施HashMap,使其保留WeakReference<Fragment>而不是Fragment s。请注意,这需要您更改getFragment方法,如下所示:

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

    这与你的问题无关......这只是我注意到的事情,我想我会引起你的注意。将WeakReferences保留到Fragment将允许您利用垃圾收集器为您确定可达性的能力,因此您不必自己执行此操作。