web-dev-qa-db-fra.com

FragmentPagerAdapter notifyDataSetChanged ne fonctionne pas

J'ai un FragmentPagerAdapter. Sa méthode getItem peut renvoyer un fragment en fonction des données dont il dispose de l'extérieur. Après avoir mis à jour les données, il est supposé afficher. J'appelle notifyDataSetChanged et pourtant rien ne s'est passé. Je DID substitue la méthode getItemPosition pour renvoyer 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;
    }
...

Et la mise à jour de l'extérieur est dans un événement de clic qui définit la variable fragmentDisplayInfo var. J'ai débogué et constaté que la variable fragmentDisplayInfo était bien initialisée et que la méthode getItemPosition retournait POSITION_NONE, mais la méthode getItem n'était même pas appelée. Pourquoi donc?

MODIFIER:

Si vous ne l'aviez pas fait également, veuillez noter qu'une partie surchargée de l'adaptateur:

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

Je ne suis pas sûr de cela, mais vous pouvez essayer d'utiliser FragmentStatePagerAdapter au lieu de FragmentPagerAdapter. Le problème, c’est que j’ai aussi rencontré ce problème et que cela m’a aidé

40
Nik Myers

Ce que dit Nik Myers est correct. Cependant, il manque une pièce. Lorsque notifyDataSetChanged est appelé, la méthode getItemPosition est appelée. Vous devez remplacer ceci pour que les fragments soient rechargés.

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

J'ai rencontré le même problème lorsque je travaillais sur mon dernier projet. J'ai donc trouvé peu de solution.

  1. en remplaçant getItemPosition dans l'adaptateur de pageur, mais ce n'est pas une bonne idée.

    @Override
    public int getItemPosition(Object object) {
        // it will recreate all Fragments when
        // notifyDataSetChanged is called
        return POSITION_NONE;
    }
    
  2. Le second est cabezas Solution.

  3. La solution la plus stable remplace getItemPosition de la manière suivante:

        @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
Ankit Demonstrate

aucune des solutions données ci-dessus ne fonctionne pour moi. Alors espérons que la solution ci-dessous peut vous être utile. 

Dans mon code, j'ai 2 fragments dans viewPager. Un est utilisé pour 3 EditTexts et 1 bouton et un autre fragment a RecyclerView. En cliquant sur un bouton, ma valeur va à recyclerView, mais elle ne se met pas à jour. Alors maintenant, j'ai utilisé le code ci-dessous:

 enter image description here

J'ai appelé le notifyDataSetChanged () en cliquant sur le bouton. Mon MainActivity a une classe d'adaptateur interne qui étend la classe FragmentStatePagerAdapter. Je l'ai donc appelé avec mainActivity.mMainAdapter.notifyDataSetChanged (). J'espère que ça aide quelqu'un.

1
Rohit Singh

Chaque réponse ici ne fonctionnait pas parfaitement pour moi, mais combiner plusieurs réponses en une seule est le bon choix. 

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);
    }

}

Renvoyez POSITION_NONE uniquement pour le fragment que vous souhaitez supprimer du viewpager. Chaque autre fragment est toujours dans votre liste de fragments. N'oubliez pas de supprimer le "removeFragment" de la liste avant d'appeler notifyDataSetChanged ();

1
Orri