web-dev-qa-db-ja.com

FragmentPagerAdapter getItemは呼び出されません

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)); 
114
Kanika

KISS回答:

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

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

@BlackHatSamuraiがコメントで言及したように:

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

291
Kanika

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

_FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());
_

フラグメントを介してgetChildFragmentManager()メソッドにアクセスできますが、ネストフラグメントが必要な場合に特にそのフラグメントのプライベートFragmentManagerを返すため、これは機能しました。これが私と同じ問題を抱えている人の助けになることを願っています!!

  • ただし、getChildFragmentManager()を使用するには、APIの最小バージョンが少なくとも17 (4.2)である必要があるため、ギアにレンチが必要になる場合があります。もちろん、サポートライブラリv4のフラグメントを使用している場合は問題ありません。
151
Jraco11

@kanikaと@ Jraco11が投稿した内容を実行しましたが、まだ問題がありました。

だから、多くの変更の後、私のために働いて、FragmentPagerAdapterに次のコードが追加されたものを見つけました:

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

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

4
Jorge Casariego

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

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

2
Maddy

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

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

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

long getItemId (int position)

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

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

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

FragementStatePagerAdapterを使用するか、int getItemPosition (Object object)POSITION_NONEを返すのは間違っています。キャッシュは取得されません。

2
vedant

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

pagerAdapter.instantiateItem(viewPager, TAB_POS)
2
B-GangsteR

おそらく、リスナーの配列ではなく、tabLayout.setOnTabSelectedListenerに1つのリスナーだけのスペースがあるため、tab-layoutにリスナーを設定すると、これが呼び出されないことがわかりました。

0
Oliver Dixon