web-dev-qa-db-ja.com

FragmentPagerAdapter notifyDataSetChangedが機能しない

FragmentPagerAdapterを入手しました。 getItemメソッドは、外部からのデータに応じてフラグメントを返すことができます。データを更新した後、表示すると仮定してnotifyDataSetChangedを呼び出しましたが、何も起こりませんでした。 I DID= getItemPositionメソッドをオーバーライドしてPOSITION_NONEを返す:

public static class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener,
        ViewPager.OnPageChangeListener
{
    private final Context mContext;
    private final TabHost mTabHost;
    private final ViewPager mViewPager;
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    private PagerTabsFragments fragmentDisplayInfo = null; // for now only a
                                                            // single size
                                                            // back
                                                            // stack

    static class PagerTabsFragments
    {
        public int tabPosition;
        public Fragment fragmentToDisplay;
        public Object fragmentInfo;

        public PagerTabsFragments(int tab, Fragment frag, Object info)
        {
            tabPosition = tab;
            fragmentToDisplay = frag;
            fragmentInfo = info;
        }
    }

    public void SetFragmentToDisplay(int tabPosition, Fragment frag, Object info)
    {
        fragmentDisplayInfo = new PagerTabsFragments(tabPosition, frag, info);
        notifyDataSetChanged();
    }

    public void CancelFragmentToDisplay()
    {
        fragmentDisplayInfo = null;
    }
...
@Override
    public Fragment getItem(final int position)
    {
        if ((fragmentDisplayInfo != null) && (fragmentDisplayInfo.tabPosition == position))
        {
            return fragmentDisplayInfo.fragmentToDisplay;
        }
        final TabInfo info = mTabs.get(position);
        return Fragment.instantiate(mContext, info.clss.getName(), info.args);
    }

    @Override
    public int getItemPosition(Object item)
    {
        if (fragmentDisplayInfo == null)
        {
            return super.getItemPosition(item);
        }
        return POSITION_NONE;
    }
...

また、外部からの更新は、fragmentDisplayInfo varを設定するクリックイベントで行われます。デバッグして、fragmentDisplayInfoが実際に初期化され、getItemPositionメソッドがPOSITION_NONEを返すことを確認しましたが、getItemメソッドは呼び出されません。何故ですか?

編集:

まだ行っていない場合は、アダプターの一部をオーバーライドしていることに注意してください。

 @Override
public int getItemPosition(Object item)
{
    return POSITION_NONE;
}
32
Yonatan Nir

これについてはわかりませんが、FragmentStatePagerAdapterの代わりにFragmentPagerAdapterを使用してみてください。問題は、私もこの問題に遭遇したことです。

47
Nik Myers

ニックマイヤーズの言うことは正しい。しかし、欠けている部分があります。 notifyDataSetChangedが呼び出されると、メソッドgetItemPositionが呼び出されます。フラグメントをリロードするには、これをオーバーライドする必要があります。

 @Override
    public int getItemPosition(Object object) {
        // Causes adapter to reload all Fragments when
        // notifyDataSetChanged is called
        return POSITION_NONE;
    }
66
Skywalker

私は最後のプロジェクトに取り組んでいたときに、同様の問題に直面しました。だから私はいくつかの解決策を見つけました。

  1. ページャアダプタでgetItemPositionをオーバーライドすることにより、これは良いアイデアではありません。

    @Override
    public int getItemPosition(Object object) {
        // it will recreate all Fragments when
        // notifyDataSetChanged is called
        return POSITION_NONE;
    }
    
  2. 2番目は cabezas Solutionです。

  3. ほとんどの安定したソリューションは、以下の方法でgetItemPositionをオーバーライドします。

        @Override
        public int getItemPosition(Object object) {
            if (object instanceof MyFragment) {
                // Create a new method notifyUpdate() in your fragment 
                // it will get call when you invoke 
                // notifyDatasetChaged();
                ((MyFragment) object).notifyUpdate();
            }
            //don't return POSITION_NONE, avoid fragment recreation.
            return super.getItemPosition(object);
        }
    
3

上記の解決策のどれも私には機能しません。したがって、以下の解決策があなたに役立つことを願っています。

私のコードでは、viewPagerに2つのフラグメントがあります。 1つは3つのEditTextsと1つのボタンに使用され、もう1つのフラグメントにはRecyclerViewがあります。ボタンをクリックすると、私の値はrecyclerViewになりますが、更新されません。だから、今、私は以下のコードを使用しました:

enter image description here

ボタンのクリック時にnotifyDataSetChanged()を呼び出しました。私MainActivityにはFragmentStatePagerAdapterクラスを拡張する内部アダプタークラスがあります。そこで、mainActivity.mMainAdapter.notifyDataSetChanged()。それが誰かを助けることを願っています。

1
Rohit Singh

ここでのすべての答えは私には完璧に機能しませんでしたが、複数の答えを1つにまとめることは正しい選択です。

public final class SomeFragment extends FragmentStatePagerAdapter{
    private final List<Fragment> fragments;
    private Fragment removeFragment; //Fragment to be removed in the next notifydatasetchanged


    @Override
    public int getItemPosition(final Object object) {
       return object.equals(this.removeFragment) ? FragmentStatePagerAdapter.POSITION_NONE : this.fragments.indexOf(object);
    }

}

ビューページャーから削除したいフラグメントに対してのみPOSITION_NONEを返します。他のすべてのフラグメントはまだフラグメントリストにあります。 notifyDataSetChanged()を呼び出す前に、リストから「removeFragment」を削除することを忘れないでください。

1
Orri