24

我正在使用此示例使用 FragmentStatePagerAdapter 。

MyAdapter 类实现如下:

public static class MyAdapter extends FragmentStatePagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

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

        @Override
        public Fragment getItem(int position) {
            return ArrayListFragment.newInstance(position);
        }
    }

ListFragment 类包括以下创建新实例的方法:

    /**
     * Create a new instance of CountingFragment, providing "num"
     * as an argument.
     */
    static ArrayListFragment newInstance(int num) {
        ArrayListFragment f = new ArrayListFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

当我在我的活动中创建一个新的片段状态寻呼机适配器时,getItem会调用它,然后调用newInstanceListFragment 类中的方法。当我想创建一个新片段时,这很棒。

但是我不清楚如何修改getItem(如果甚至需要)以在片段对象已经存在时获取片段对象以及用户页面从例如第 2 页到第 1 页。我希望我的 Activity 之前检索现有的创建片段,以便它可以运行AsyncMethod位于片段类中的内部类。

4

6 回答 6

44

我认为解决方案比提供的答案简单得多。

如果您查看 的来源FragmentStatePagerAdapter.instantiateItem(),您会注意到它instantiateItem()为您处理此逻辑,因此您的实现getItem()应该始终返回一个新实例。

因此,为了返回现有的 Fragment,只需执行以下操作(假设您从 调用ViewPager):

Fragment f = (Fragment) getAdapter().instantiateItem(this, getCurrentItem());
于 2013-10-06T14:52:29.760 回答
9

虽然@imiric 的解决方案非常简洁,但它需要了解类的实现仍然让我感到困扰。我的解决方案包括将以下内容添加到您的适配器中,它应该与 FragmentStatePagerAdapter 表现良好,可能会破坏片段:

    private SparseArray<WeakReference<Fragment>> mFragments = new SparseArray<>();

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment f = (Fragment) super.instantiateItem(container, position);
        mFragments.put(position, new WeakReference<>(f));  // Remember what fragment was in position
        return f;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        mFragments.remove(position);
    }

    public Fragment getFragment(int position) {
        WeakReference<Fragment> ref = mFragments.get(position);
        Fragment f = ref != null ? ref.get() : null;
        if (f == null) {
            Log.d(TAG, "fragment for " + position + " is null!");
        }
        return f;
    }
于 2014-05-02T11:36:26.530 回答
6

我已经实现了与您所拥有的类似的东西。我像这样扩展了FragmentPagerAdapter课程:

public class ContactsFragmentPagerAdapter extends FragmentPagerAdapter {
    ActionBar mActionBar;
    private List<Fragment> mFragments;

    public ContactsFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        mFragments = fragments;
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    public void setActionBar(ActionBar bar) {
        mActionBar = bar;
    }
}

List请注意,我已向构造函数添加了一个参数以传入Fragment对象。这样getItem(),此类的方法可以返回任何扩展Fragment的类或其任何子类,而不是ArrayListFragment像您所做的那样仅返回一个特定的类。

Activity我实例化我的子类的地方,FragmentPagerAdapter我传入了Fragment对象列表:

类实例化 FragmentPagerAdapter

public final class ContactManager extends Activity {
    private ContactsFragmentPagerAdapter mAdapter;
    private ViewPager mPager;
    public ActionBar mActionBar;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.contact_manager);

        List<Fragment> fragments = new Vector<Fragment>();
        fragments.add(Fragment.instantiate(this, ContactsListFragment.class.getName()));
        fragments.add(Fragment.instantiate(this, GroupsListFragment.class.getName()));
        mAdapter = new ContactsFragmentPagerAdapter(this.getFragmentManager(), fragments);

        mPager = (ViewPager) findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);

        mPager.setOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrollStateChanged(int arg0) {}

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {}

            @Override
            public void onPageSelected(int arg0) {
                mActionBar.getTabAt(arg0).select();
            }
        });

    }

}

通过访问变量“fragments”,您可以访问先前创建Fragment的,以便您可以运行该Fragment.

于 2012-10-24T20:45:39.510 回答
4
public class MyPagerAdapter extends FragmentStatePagerAdapter {
    final Context m_context;
    final WeakReference<Fragment>[] m_fragments;

    public DetailPagerAdapter(FragmentManager fm) {
        super(fm);
        m_context = ...
                m_fragments = new WeakReference[enter size here];
    }

    @Override
    public Fragment getItem(int position) {
        final Fragment fragment = instantiate your fragment;
        m_fragments[position] = new WeakReference<Fragment>(fragment);
        return fragment;
    }

    @Override
    public int getCount() {
        return ...
    }

    public Fragment getFragment(final int position) {
        return m_fragments[position] == null ? null :
            m_fragments[position].get();
    }
}
于 2013-03-12T19:13:28.433 回答
0

不需要修改 FragmentPagerAdapter,因为 FragmentManager 缓存了 Fragment。所以你必须在里面找到。使用此函数按寻呼机适配器位置查找片段。

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

v4 支持 api 的示例代码。

于 2013-06-18T06:19:52.140 回答
0

我认为这可能会有所帮助:

class HomePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

    private val fragmentConstructors: List<() -> Fragment> by lazy {
        listOf(
                ::AuctionLotsFragment,
                ::ChatListFragment,
                ::MarketHomeFragment,
                ::WalletSectionsFragment,
                ::SettingsFragment
        )
    }

    private val fragments: HashMap<Int, WeakReference<Fragment>> by lazy {
        HashMap()
    }

    override fun getCount(): Int = fragmentConstructors.size

    override fun getItem(position: Int): Fragment {
        return fragments[position]?.get() ?: this.createFragmentForPosition(position)
    }

    private fun createFragmentForPosition(position: Int): Fragment {
        val fragment = fragmentConstructors[position].invoke()
        fragments[position] = WeakReference(fragment)
        return fragment
    }

}
于 2021-02-11T10:46:12.850 回答