web-dev-qa-db-fra.com

Mettre à jour ViewPager dynamiquement?

Je ne peux pas mettre à jour le contenu dans ViewPager.

Une question: Quelle est la relation et l’usage correct des méthodes instantiateItem () et getItem () dans la classe FragmentPagerAdapter?

J'utilisais seulement getItem () pour instancier et renvoyer mes fragments:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

Cela a bien fonctionné (mais comme dit je ne peux pas changer le contenu).

J'ai donc trouvé ceci: ViewPager PagerAdapter ne mettant pas à jour la vue

En particulier celui dans lequel on parle de méthode instantiateItem ():

"Mon approche consiste à utiliser la méthode setTag () pour toute vue instanciée dans la méthode instantiateItem ()"

Alors maintenant, je veux implémenter instantiateItem () pour le faire. Mais je ne sais pas ce que je dois y retourner (return est Object) et quelle est la relation avec getItem (int position)?

J'utilise actuellement getItem pour instancier le fragment, est-ce faux? Mais alors dois-je mettre les fragments dans une variable d'instance ou ne pas implémenter getItem () du tout ...? Je ne comprends tout simplement pas.

J'ai essayé de lire la référence :

  • public abstract Fragment getItem (int position)

    Renvoie le fragment associé à une position spécifiée.

  • public Object instantiateItem (conteneur ViewGroup, int position)

    Créez la page pour la position donnée. L'adaptateur est responsable de l'ajout de la vue au conteneur indiqué ici, même s'il doit uniquement s'assurer que cela est fait au moment où il revient de finishUpdate (ViewGroup) . Paramètres

    conteneur La vue contenant dans laquelle la page sera affichée . position La position de la page à instancier.

    Résultats

    Renvoie un objet représentant la nouvelle page. Cela n'a pas besoin d'être une vue, mais peut être un autre conteneur de la page.

... mais je ne comprends toujours pas comment ils sont liés et ce que je dois faire.

Voici mon code. J'utilise le package de support v4.

ViewPagerTest 

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

    @Override
    public int getCount() {
        return slideCount;
    }

    public void setData(String[] data) {
        this.data = data;
    }

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

Mon Fragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

Voici aussi quelqu'un avec un problème similaire, pas de réponse ...

http://www.mail-archive.com/[email protected]/msg200477.html

283
Ixx

Lorsque vous utilisez FragmentPagerAdapter ou FragmentStatePagerAdapter, il est préférable de traiter uniquement avec getItem() et de ne pas toucher à instantiateItem() du tout. L'interface instantiateItem()-destroyItem()-isViewFromObject() sur PagerAdapter est une interface de niveau inférieur que FragmentPagerAdapter utilise pour implémenter l'interface beaucoup plus simple getItem().

Avant d'entrer dans cela, je devrais préciser que 

Si vous souhaitez remplacer les fragments actuellement affichés, vous devez éviter FragmentPagerAdapter et utiliser FragmentStatePagerAdapter.

Une version antérieure de cette réponse faisait l'erreur d'utiliser FragmentPagerAdapter pour son exemple. Cela ne fonctionnera pas car FragmentPagerAdapter ne détruit jamais un fragment après sa première visualisation.

Je ne recommande pas les solutions de contournement setTag() et findViewWithTag() fournies dans le message que vous avez lié. Comme vous l'avez découvert, l'utilisation de setTag() et findViewWithTag() ne fonctionne pas avec les fragments, ce n'est donc pas une bonne correspondance.

La bonne solution consiste à remplacer getItemPosition(). Lorsque notifyDataSetChanged() est appelé, ViewPager appelle getItemPosition() sur tous les éléments de son adaptateur pour voir s'ils doivent être déplacés ou supprimés. 

Par défaut, getItemPosition() renvoie POSITION_UNCHANGED, ce qui signifie: "Cet objet convient parfaitement, ne le détruisez pas et ne le supprimez pas." Retourner POSITION_NONE corrige le problème en disant plutôt: "Cet objet n'est plus un élément que je suis en train d'afficher, supprimez-le." Cela a donc pour effet de supprimer et de recréer chaque élément de votre adaptateur. 

C'est une solution tout à fait légitime! Avec ce correctif, notifyDataSetChanged se comporte comme un adaptateur standard sans recyclage de vue. Si vous implémentez ce correctif et que les performances sont satisfaisantes, vous êtes prêt pour la course. Travail accompli.

Si vous avez besoin de meilleures performances, vous pouvez utiliser une implémentation plus sophistiquée de getItemPosition(). Voici un exemple pour un pager créant des fragments à partir d'une liste de chaînes:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

Avec cette implémentation, seuls les fragments affichant de nouveaux titres seront affichés. Tous les fragments affichant des titres qui sont encore dans la liste seront déplacés vers leur nouvel emplacement dans la liste, et les fragments avec des titres qui ne sont plus du tout dans la liste seront détruits.

Que se passe-t-il si le fragment n'a pas été recréé, mais doit quand même être mis à jour? Les mises à jour d'un fragment vivant sont mieux traitées par le fragment lui-même. C'est l'avantage d'avoir un fragment, après tout - c'est son propre contrôleur. Un fragment peut ajouter un auditeur ou un observateur à un autre objet dans onCreate(), puis le supprimer dans onDestroy(), en gérant ainsi les mises à jour. Vous n'avez pas besoin de mettre tout le code de mise à jour dans getItem() comme vous le faites dans un adaptateur pour un type ListView ou un autre type AdapterView.

Une dernière chose - le fait que FragmentPagerAdapter ne détruit pas un fragment ne signifie pas que getItemPosition est totalement inutile dans un FragmentPagerAdapter. Vous pouvez toujours utiliser ce rappel pour réorganiser vos fragments dans ViewPager. Cependant, il ne les supprimera jamais complètement de FragmentManager.

571
Bill Phillips

Au lieu de renvoyer POSITION_NONE à partir de getItemPosition() et de provoquer une reconstitution de vue complète, procédez comme suit:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

Vos fragments doivent implémenter l'interface UpdateableFragment:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

et l'interface:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

Votre classe de données:

public class UpdateData {
    //whatever you want here
}
132
M-WaJeEh

pour ceux qui sont toujours confrontés au même problème que celui auquel je faisais face auparavant lorsque j’ai un ViewPager avec 7 fragments. la valeur par défaut pour ces fragments pour charger le contenu anglais à partir du service api mais le problème ici que je veux changer la langue à partir de l’activité paramètres et une fois terminé de l'utilisateur et charge le contenu arabe si l'utilisateur choisit l'arabe ici ce que j'ai fait pour travailler depuis la première fois 

1- Vous devez utiliser FragmentStatePagerAdapter comme mentionné ci-dessus.

2-on mainActivity i remplacer le onResume et fait ce qui suit 

 if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3-i a remplacé getItemPosition () dans mPagerAdapter et lui a renvoyé POSITION_NONE.

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

fonctionne comme un charme

20
Ziad Gholmish

J'ai rencontré ce problème et l'ai finalement résolu aujourd'hui, alors j'écris ce que j'ai appris et j'espère que cela sera utile pour quelqu'un qui est nouveau sur la version ViewPager d'Android et qu'il met à jour comme je le fais. J'utilise FragmentStatePagerAdapter dans l'API de niveau 17 et je n'ai actuellement que 2 fragments. Je pense qu'il doit y avoir quelque chose de pas correct, corrigez-moi, merci .enter image description here

  1. Les données sérialisées doivent être chargées en mémoire. Cela peut être fait avec un CursorLoader/AsyncTask/Thread. Le chargement automatique dépend de votre code. Si vous utilisez un CursorLoader, il est chargé automatiquement car il existe un observateur de données enregistré.

  2. Une fois que vous avez appelé viewpager.setAdapter(pageradapter), la fonction getCount() de l'adaptateur est appelée en permanence pour générer des fragments. Ainsi, si des données sont en cours de chargement, getCount() peut renvoyer 0, vous n'avez donc pas besoin de créer de fragments factices pour aucune donnée affichée.

  3. Une fois les données chargées, l'adaptateur ne crée pas de fragments automatiquement car getCount() est toujours égal à 0. Nous pouvons donc définir le numéro des données réellement chargées à renvoyer par getCount(), puis appeler le notifyDataSetChanged() de l'adaptateur. ViewPager commence à créer des fragments (uniquement les 2 premiers fragments) à l'aide de données en mémoire. C'est fait avant que notifyDataSetChanged() soit retourné. Alors le ViewPager a les bons fragments dont vous avez besoin.

  4. Si les données de la base de données et de la mémoire sont toutes les deux mises à jour (écriture continue), ou si seules les données en mémoire le sont (écriture arrière), ou si seules les données de la base de données sont mises à jour. Dans les deux derniers cas, si les données ne sont pas automatiquement chargées de la base de données dans la mémoire (comme indiqué ci-dessus) . L'adaptateur ViewPager et le pager traitent uniquement les données en mémoire.

  5. Ainsi, lorsque les données en mémoire sont mises à jour, il suffit d'appeler la fonction notifyDataSetChanged() de l'adaptateur. Étant donné que le fragment est déjà créé, la fonction onItemPosition() de l'adaptateur sera appelée avant le retour de notifyDataSetChanged(). Rien ne doit être fait dans getItemPosition(). Ensuite, les données sont mises à jour.

14
oscarthecat

Essayez destroyDrawingCache() sur ViewPager après notifyDataSetChanged() dans votre code.

12
czaku

Après des heures de frustration en essayant toutes les solutions ci-dessus pour surmonter ce problème et en essayant de nombreuses solutions sur d'autres questions similaires, telles que ceci , ceci et ceci que tous ont échoué avec moi pour résoudre ce problème. et faire en sorte que ViewPager détruise l'ancien Fragment et remplisse pager par le nouveau Fragments. J'ai résolu le problème comme suit:

1) Transforme la classe ViewPager en extension FragmentPagerAdapter comme suit:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) Créez un élément pour la ViewPager qui stocke la title et la fragment comme suit:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) Demander au constructeur de ViewPager de prendre mon instance FragmentManager pour la stocker dans ma class comme suit:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) Créez une méthode pour redéfinir les données adapter avec les nouvelles données en supprimant toute la précédente fragment de la fragmentManager elle-même afin que la adapter définisse à nouveau la nouvelle fragment de la nouvelle liste comme suit:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) Dans le conteneur Activity ou Fragment, ne réinitialisez pas l'adaptateur avec les nouvelles données. Définissez les nouvelles données à l'aide de la méthode setPagerItems avec les nouvelles données comme suit:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

J'espère que ça aide.

10
Sami Eltamawy

Pour une raison quelconque, aucune des réponses ne fonctionnait pour moi, alors j'ai dû remplacer la méthode restoreState sans appeler super dans fragmentStatePagerAdapter. Code:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
7
hordurh

J'ai légèrement modifié la solution fournie par Bill Phillips pour répondre à mes besoins

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

de sorte que la getItemPosition() renvoie POSITION_NONE uniquement pour les fragments qui se trouvent actuellement dans la variable FragmentManager lorsque la variable getItemPosition est appelée . (Notez que cette FragmentStatePager et la ViewPager associée à il est contenu dans un fragment pas dans une activité)

3
adwait

J'avais un problème similaire mais je ne voulais pas faire confiance aux solutions existantes (noms de balises codées en dur, etc.) et je ne pouvais pas utiliser la solution de M-WaJeEh pour moi. Voici ma solution:

Je garde des références aux fragments créés dans getItem dans un tableau. Cela fonctionne bien tant que l'activité n'est pas détruite pour des raisons de configuration. Changement ou manque de mémoire ou autre (-> lors du retour à l'activité, les fragments reviennent à leur dernier état sans que 'getItem' soit appelé à nouveau et donc sans mettre à jour le tableau ).

Pour éviter ce problème, j'ai implémenté instantiateItem (ViewGroup, int) et mis à jour mon tableau là-bas, comme ceci:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

Donc, d’un côté, je suis heureux d’avoir trouvé une solution qui marche pour moi et que je veuille la partager avec vous, mais je voulais aussi demander si quelqu'un d’autre avait essayé quelque chose de similaire et s’il y avait une raison pour que je ne devrais pas le faire. le faire comme ça? Jusqu'à présent, cela fonctionne très bien pour moi ...

2
jpm

J'ai vécu le même problème et j'ai cherché trop de fois. Toute réponse donnée dans stackoverflow ou via google n’était pas une solution à mon problème. Mon problème était facile. J'ai une liste, je montre cette liste avec viewpager. Lorsque j'ajoute un nouvel élément en tête de la liste et que j'actualise les remarques du viewpager. Ma solution finale était très facile à utiliser. Lorsqu'un nouvel élément est ajouté à la liste et que vous souhaitez l'actualiser. Définissez d'abord l'adaptateur viewpager sur null, puis recréez l'adaptateur et définissez-y sur viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

Assurez-vous que votre adaptateur doit étendre FragmentStatePagerAdapter

1
nebyan

Si vous souhaitez utiliser FragmentStatePagerAdapter, consultez https://code.google.com/p/Android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner% 20Summary% 20Stars & groupby = & sort = & id = 37990 . Il existe des problèmes avec FragmentStatePagerAdapter qui peuvent ou non gêner votre cas d'utilisation. 

En outre, le lien a peu de solutions aussi .. peu peut convenir à votre condition.

1
cgr

J'utilise EventBus library pour mettre à jour le contenu Fragment dans ViewPager. La logique est simple, tout comme le document de EventBus comment procéder . Il n'est pas nécessaire de contrôler l'instance FragmentPagerAdapter. Le code est ici:

1: Définir les événements

Définissez le message à mettre à jour. 

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2.Préparer des abonnés

Ecrivez ci-dessous le code dans le fragment qui doit être mis à jour.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3. événements postérieurs

Ecrivez ci-dessous le code dans une autre variable Activity ou Fragment qui doit mettre à jour le paramètre 

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
1
Fantasy Fang

Je sais que je suis en retard pour le parti. J'ai résolu le problème en appelant TabLayout#setupWithViewPager(myViewPager); juste après FragmentPagerAdapter#notifyDataSetChanged();

0
theapache64

Cela pourrait être utile à quelqu'un - dans mon cas, lors de l'insertion d'une nouvelle page, le pager de vue demandait deux fois la position d'un fragment existant, mais ne demandait pas la position du nouvel élément, ce qui entraînait un comportement incorrect et l'absence d'affichage des données.

  1. Copiez le source pour FragmentStatePagerAdapter (semble ne pas avoir été mis à jour depuis des lustres).

  2. Remplacer notifyDataSetChanged ()

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  3. Ajoutez un contrôle de cohérence à destroyItem () pour éviter les plantages:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    
0
Meanman

Voici mon implémentation qui intègre les informations de @Bill PhillipsOne obtient la plupart du temps la mise en cache des fragments, sauf lorsque les données ont changé. Simple et semble bien fonctionner.

MyFragmentStatePagerAdapter.Java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}

MyActivity.Java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
0
voam

J'ai parcouru toutes les réponses ci-dessus et un certain nombre d'autres publications, mais je n'ai toujours pas trouvé quelque chose qui fonctionnait pour moi (avec différents types de fragments, avec l'ajout et la suppression dynamiques d'onglets). L’approche suivante de FWIW est ce qui a fonctionné pour moi (au cas où quelqu'un aurait les mêmes problèmes). 

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
0
John O'Reilly

Utilisez FragmentStatePagerAdapter au lieu de FragmentPagerAdapter Si vous souhaitez recréer ou recharger un fragment sur une base d'index Par exemple, si vous souhaitez recharger un fragment autre que FirstFragment, vous pouvez vérifier l'instance et la position renvoyée de la manière suivante

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
0
HemangNirmal

Cette solution ne fonctionnera pas pour tout le monde, mais dans mon cas, chaque fragment de mon ViewPager est une classe différente et un seul d'entre eux existe à la fois. 

Avec cette contrainte, cette solution est sûre et devrait pouvoir être utilisée en production en toute sécurité.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

Si vous avez plusieurs versions du même fragment, vous pouvez utiliser cette même stratégie pour appeler des méthodes sur ces fragments afin de déterminer s'il s'agit du fragment que vous souhaitez mettre à jour.

0
Kevin Grant

J'avais essayé tellement d'approches différentes, aucune ne réglait vraiment mon problème. Voici comment je le résous avec un mélange de solutions fournies par vous tous. Merci tout le monde.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

Je veux seulement actualiser la page 0 après onResume ().

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

Dans mon FragmentsMain, il existe un entier public "page" qui peut me dire si c'est la page que je veux actualiser.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
0
Ted Hsieh