FragmentPagerAdapter getItemは呼び出されません


123

FragmentPagerAdapterでフラグメントを再利用できません。.destroyItem()メソッドを使用して、フラグメントを削除していますが、再びgetItem()を呼び出していません。

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

そしてFragmentActivityでは、

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 

3
乗り越えた特別な理由はありますdestroyItem()か?それは必要ありません。
CommonsWare 2012

再度初期化するには、FragmentStatePagerAdapterを使用します。オーバーライドするときにも呼び出します。super.destroyItem(container、position、object);
faiziii 2015年

回答:


306

KISS回答:

FragmentPagerAdapterの代わりにFragmentStatePagerAdapterを使用するだけです。

私は..答えを得た私は非常に愚かな間違いをしていてまず私はこの質問を削除すると考えられますが、この答えは、代わりに同じ問題に直面している誰かを助けるFragmentPagerAdapter、使用しますFragmentStatePagerAdapter

@BlackHatSamuraiがコメントで述べたように:

これが機能する理由は、FragmentStatePagerAdapter使用されていないフラグメントとして破棄するためです。FragmentPagerAdapterではない。


どうもありがとうございました。
Priya 2013年

1
別の「私」にもなりたくない!投稿、でもそう>。<質問を削除しないでくれてありがとう
Paul Ruiz 2013

34
これが機能する理由は、使用されていないフラグメントとしてFragmentStatePagerAdapterが破棄されるためです。FragmentPagerAdapterにはありません。
BlackHatSamurai 2013年

3
発生している特定の問題を検索しているときにこれを見つける可能性のある人のための将来の参照用。FragmentPagerAdapterとFragmentStatePagerAdapterの両方を確認してください。理由によって動作が異なり、特定の用途ではどちらか一方が必要になる場合があります。
Chris Stewart

2
@najibputhawala私はFragmentStatePagerAdapterを使用しましたが、それでも同じ問題に直面しています。getItem()は呼び出されません
sam_k

168

を使用してFragmentStatePagerAdapteronCreateView、ビューページャーで子フラグメントに対して呼び出されなかったのと同様の問題である私の問題は完全には修正されませんでした。私は実際に自分のFragmentPagerAdapter内側を別の内側Fragment入れ子にしているため、FragmentManagerそれらはすべて共有され、古いフラグメントのインスタンスを保持しています。修正は、代わりにホストのフラグメントのgetChildFragmentManagerコンストラクタにのインスタンスをフィードすることでしたFragmentPagerAdapter。何かのようなもの...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

このgetChildFragmentManager()メソッドはフラグメントを介してアクセス可能であり、FragmentManager特にフラグメントのネストが必要な状況でそのフラグメントのプライベートを返すため、これは私にとってはうまくいきました。これが私と同じ問題を抱えている可能性がある人に役立つことを願っています!!

  • ただしgetChildFragmentManager()、最低限のAPIバージョンを使用するには少なくとも17 (4.2)でなければならないので、ギアにレンチを投げる可能性があることに注意してください。もちろん、サポートライブラリv4のフラグメントを使用している場合は問題ありません。

25
これが正解です。問題は、他のフラグメントにネストされたフラグメントがgetFragmentManager()ではなくgetChildrenFragmentManager()を使用する必要があるためです。
Shihpeng 2015

どうもありがとう、この答えを見つけるのに私は永遠にかかりました!
Shpongoloid 2015

@shihpengに同意します。これが正解です。
レイモンドルカンタ2015

これは私にとって修正でした。回答を送信していただきありがとうございます
user3734429

ドキュメントでは、ウォークスルーでこれを実際に呼び出す必要があります。ViewPagerがフラグメント内にロードされることは非常に現実的です。この回答を投稿していただきありがとうございます。
勤務

7

オーバーライド long getItemId (int position)

FragmentPagerAdapterを使用して作成したフラグメントをキャッシュしgetItemます。私は同じ問題に直面していました-呼び出しnotifyDataSetChanged() getItemが呼び出されていなかった後でも。

これは実際には機能であり、バグではありません。getItemIdフラグメントを正しく再利用できるように、オーバーライドする必要があります。フラグメントを削除しているため、位置が変化しています。ドキュメントで述べたように:

long getItemId (int position)

指定された位置にあるアイテムの一意の識別子を返します。

デフォルトの実装は、指定された位置を返します。アイテムの位置を変更できる場合、サブクラスはこのメソッドをオーバーライドする必要があります。

各フラグメントに一意のIDを指定するだけで完了です。

使用FragementStatePagerAdapterまたは返却POSITION_NONEint getItemPosition (Object object)間違っています。キャッシュは取得されません。


これが正解でした。でフラグメントに異なるIDを指定し、フラグメントを削除する必要がある場合は返すgetItemIdように調整getItemPositionするPOSITION_NONE必要がありました。そのための列挙型フラグがあります。その後getItem呼び出されます。
MuratKaragöz、

@MuratKaragözに+50をありがとう:)
ヴェダント

5

@kanikaと@ Jraco11が投稿したことを行いましたが、まだ問題がありました。

そのため、多くの変更を加えた結果、私にとってはうまくいき、次のコードがFragmentPagerAdapterに追加されました。

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

私が読んだ内容によると、getItemPositionは、アイテムを更新するかどうかをViewPagerに通知し、表示されている位置のアイテムが変更されていない場合は更新を回避するために使用されます。


2

2つの異なるシナリオがあります。1。)すべてのページャーに同じレイアウトがあります。その場合、PagerAdapterによってカスタムアダプターを拡張し、単一のレイアウトを返すことをお勧めします。

2.)ページャーごとに異なるレイアウトがあります。その場合、カスタムアダプターをFragmentStatePagerAdapterで拡張し、ページャーごとに異なるフラグメントを返すとよいでしょう。


2

メソッドgetItem()は、新しいアイテムを作成するためにのみ使用されます。いったん作成すると、このメソッドは呼び出されません。アダプターで使用されている通貨のアイテムを取得する必要がある場合は、次のメソッドを使用します。

pagerAdapter.instantiateItem(viewPager, TAB_POS)

0

タブレイアウトにリスナーを設定すると、おそらくリスナーtabLayout.setOnTabSelectedListenerの配列ではなく1つのリスナー用のスペースしかないため、これが呼び出されないことがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.