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));
KISS回答:
FragmentPagerAdapter の代わりに FragmentStatePagerAdapter を使用するだけです。
私は答えを得ました..まず、私は非常に愚かな間違いをしているのでこの質問を削除することを考えましたが、この答えはFragmentPagerAdapter
の代わりにFragmentStatePagerAdapter
を使用する同じ問題に直面している人を助けます。
@BlackHatSamuraiがコメントで言及したように:
これが機能する理由は、
FragmentStatePagerAdapter
が使用されていないフラグメントとして破棄されるためです。FragmentPagerAdapter
はしません。
FragmentStatePagerAdapter
を使用しても、ビューページャー内の子フラグメントに対してonCreateView
が呼び出されないという同様の問題である私の問題は完全には修正されませんでした。私は実際に別のFragmentPagerAdapter
内にFragment
を入れ子にするです。したがって、FragmentManager
はそれらすべてで共有され、古いフラグメントのインスタンスを保持します。修正は、代わりにgetChildFragmentManager
のインスタンスをホストフラグメントのFragmentPagerAdapter
のコンストラクターに供給することでした。何かのようなもの...
_FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());
_
フラグメントを介してgetChildFragmentManager()
メソッドにアクセスできますが、ネストフラグメントが必要な場合に特にそのフラグメントのプライベートFragmentManager
を返すため、これは機能しました。これが私と同じ問題を抱えている人の助けになることを願っています!!
getChildFragmentManager()
を使用するには、APIの最小バージョンが少なくとも17 (4.2)
である必要があるため、ギアにレンチが必要になる場合があります。もちろん、サポートライブラリv4のフラグメントを使用している場合は問題ありません。@kanikaと@ Jraco11が投稿した内容を実行しましたが、まだ問題がありました。
だから、多くの変更の後、私のために働いて、FragmentPagerAdapterに次のコードが追加されたものを見つけました:
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
私が読んだことによると、getItemPositionはViewPagerを通知するために使用され、アイテムを更新するかどうか、および表示位置のアイテムが変更されていない場合は更新を回避します。
2つの異なるシナリオがあります。1.)すべてのページャーに同じレイアウトがあります:その場合、PagerAdapterによってカスタムアダプターを拡張し、単一のレイアウトを返すとよいでしょう。
2.)ページャーごとに異なるレイアウトがある場合:その場合は、FragmentStatePagerAdapterによってカスタムアダプターを拡張し、ページャーごとに異なるフラグメントを返すとよいでしょう。
long getItemId (int position)
をオーバーライドする
FragmentPagerAdapter
は、getItem
を使用して作成したフラグメントをキャッシュします。私は同じ問題に直面していました-notifyDataSetChanged()
を呼び出した後でもgetItem
は呼び出されていませんでした。
これは実際には機能であり、バグではありません。フラグメントを正しく再利用できるように、getItemId
をオーバーライドする必要があります。フラグメントを削除しているため、位置が変化しています。ドキュメントで述べたように:
long getItemId (int position)
指定された位置にあるアイテムの一意の識別子を返します。
デフォルトの実装は、指定された位置を返します。 アイテムの位置が変更される可能性がある場合、サブクラスはこのメソッドをオーバーライドする必要があります。
各フラグメントに一意のIDを指定するだけで完了です。
FragementStatePagerAdapter
を使用するか、int getItemPosition (Object object)
でPOSITION_NONE
を返すのは間違っています。キャッシュは取得されません。
method getItem()
は、新しいアイテムを作成するためにのみ使用されます。一度作成すると、このメソッドは呼び出されません。アダプターが使用している通貨のアイテムを取得する必要がある場合は、次の方法を使用します。
pagerAdapter.instantiateItem(viewPager, TAB_POS)
おそらく、リスナーの配列ではなく、tabLayout.setOnTabSelectedListener
に1つのリスナーだけのスペースがあるため、tab-layoutにリスナーを設定すると、これが呼び出されないことがわかりました。