web-dev-qa-db-ja.com

Android FragmentStatePagerAdapter

私は この例 を使用して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が呼び出され、ListFragmentクラスのnewInstanceメソッドが呼び出されます。これは、新しいフラグメントを作成するときに最適です。

しかし、フラグメントオブジェクトが既に存在する場合とユーザーを取得するためにgetItem(必要な場合でも)を変更する方法はわかりませんたとえば、ページ2からページ1までのページ。アクティビティで、以前に作成された既存のフラグメントを取得して、フラグメントクラスにある内部クラスAsyncMethodを実行できるようにしたいと考えています。

22
mraviator

ソリューションは提供された回答よりもはるかに単純だと思います。

source of FragmentStatePagerAdapter.instantiateItem() を見ると、instantiateItem()がこのロジックを処理しているので、getItem()は常に新しいインスタンスを返します。

そのため、既存のFragmentを返すには、次のようにします(ViewPagerから呼び出していると想定)。

Fragment f = (Fragment) getAdapter().instantiateItem(this, getCurrentItem());
44
imiric

@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;
    }
8
qix
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();
    }
}
4
farid_z

フラグメントはFragmentManagerによってキャッシュされるため、FragmentPagerAdapterを変更する必要はありません。だからあなたはその中に見つける必要があります。この関数を使用して、ページャーアダプターの位置によってフラグメントを検索します。

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

v4サポートAPIのサンプルコード

0
Daniel De León